Wednesday, June 2, 2010

How to create minimal Spring-secured web application

The question is how to bootstrap new web application project with Spring Security support up and running.



Create Maven project using the webapp archetype

$ mvn archetype:create -DarchetypeArtifactId=maven-archetype-webapp -DartifactId=springSecurityBoot -DgroupId=qux



Add Spring Security dependencies to your pom.xml

<project ... >
  ...
  <dependencies>
    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-core</artifactId>
      <version>3.0.2.RELEASE</version>
    </dependency>
    <!-- Spring Security XSD dependency -->
    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-config</artifactId>
      <version>3.0.2.RELEASE</version>
    </dependency>
    <!-- Required to secure web application -->
    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-web</artifactId>
      <version>3.0.2.RELEASE</version>
    </dependency>
    <!-- Dependency for DelegatingFilterProxy -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>3.0.1.RELEASE</version>
    </dependency>
  </dependencies>
    ...
</project>



Add Security filter chain delegation to the web.xml

You need to intercept all requests coming to your web application and delegate them to the Spring-managed Security chain. Because web.xml doesn't support Spring IOC, you need to delegate calls from filter defined in web.xml to the Spring-managed Security Filter chain. You can achieve this with org.springframework.web.filter.DelegatingFilterProxy.

<!-- Delegate all requests to Spring Security filters chain -->
<filter>
  <filter-name>springSecurityFilterChain</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
  <filter-name>springSecurityFilterChain</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
    
<!-- Load Spring context into the webapp -->
<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>



Create Spring wiring file for webapp context

This is a default location of the context file for ContextLoaderListener:

touch src/main/webapp/WEB-INF/applicationContext.xml

All what your config does is loading Security context defined in another file:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    
  <import resource="security-context.xml"/>

</beans>



Create security configuration file

touch src/main/webapp/WEB-INF/security-context.xml

You just want to secure your entire webapp and restrict the access to the defined user.

<beans:beans xmlns="http://www.springframework.org/schema/security"
  xmlns:beans="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  http://www.springframework.org/schema/security
  http://www.springframework.org/schema/security/spring-security-3.0.xsd">

  <http auto-config='true'>
    <intercept-url pattern="/**" access="ROLE_USER"/>
  </http>
    
  <!-- In-memory user database -->

  <authentication-manager>
    <authentication-provider>
      <user-service>
        <user name="foo" password="bar" authorities="ROLE_USER"/>
      </user-service>
    </authentication-provider>
  </authentication-manager>

</beans:beans>



Run your secured webapp

mvn tomcat:run

Now you need to login to see the index.jsp page.

# -L to follow HTTP redirects returned by Spring filters 
curl -L http://localhost:8080/ssboot

<html><head><title>Login Page</title></head><body onload='document.f.j_username.focus();'>
<h3>Login with Username and Password</h3><form name='f' action='/ssboot/j_spring_security_check' method='POST'>
 <table>
    <tr><td>User:</td><td><input type='text' name='j_username' value=''></td></tr>
    <tr><td>Password:</td><td><input type='password' name='j_password'/></td></tr>
    <tr><td colspan='2'><input name="submit" type="submit"/></td></tr>
    <tr><td colspan='2'><input name="reset" type="reset"/></td></tr>
  </table>
</form></body></html>

2 comments: