Spring Security XML Namespace Configuration Example

In this Spring Security Tutorial Series we will take a look how to use Spring Security with XML Namespace Configuration with Example of authentication and access-control using <http>, <intercept-url> namespaces. In my earlier article We have seen Spring Security Java Configuration Annotation Example of Authentication and access control using @Secured, @PreAuthorize and JSR-250 @RolesAllowed annotations. As we know that Spring Security is a very powerful and highly customizable authentication and access-control framework.

Spring Security XML Namespace Configuration
XML Namespace configuration has been available since Spring Security 2.0. In Spring Framework, A namespace element is nothing but it is a more concise way of configuring an individual bean or, more powerfully, to define an alternative configuration syntax. It actually hides the underlying bean definition complexity from the user. For using the spring security namespace in your application context, you need to have the spring-security-config jar on your classpath. And finally you need to add the schema declaration to your application context file as below:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
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.xsd">
 ...
</beans>

web.xml Configuration (Setup DelegatingFilterProxy and springSecurityFilterChain)
FilterChainProxy add a single entry to web.xml and deal entirely with the application context file for managing our web security beans. It is wired using a DelegatingFilterProxy, just like in the example above, but with the filter-name set to the bean name “springSecurityFilterChain”. In this case, the bean is named “springSecurityFilterChain”, which is an internal infrastructure bean created by the namespace to handle web security.

Define the single proxy filter
springSecurityFilterChain is a mandatory name
        -Refers to an existing Spring bean with same name

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>17-Spring-Security-XML-Namespace-Config</display-name>
 <servlet>
        <servlet-name>doj</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
         <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>doj</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    
 <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>
</web-app>
Spring Security Filter Configuration


Spring Security Namespace Configuration in the Application Context file
Once you’ve added DelegatingFilterProxy and springSecurityFilterChain to your web.xml, you’re ready to start editing your application context file. Web security services are configured using the <http> element.

<?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"
 xmlns:mvc="http://www.springframework.org/schema/mvc"
 xmlns:security="http://www.springframework.org/schema/security"
 xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
  http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

 <context:component-scan base-package="com.doj.app.controller"/>
 
 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="suffix" value=".jsp"/>
  <property name="prefix" value="/WEB-INF/view/"/>
 </bean>

 <security:http>
  <security:intercept-url access="hasRole('USER')" pattern="/**" />
  <security:form-login/>
  <security:logout/>
 </security:http>


      <security:authentication-manager>
  <security:authentication-provider>
   <security:user-service>
    <security:user name="admin" password="adminpassword" authorities="ROLE_USER, ROLE_ADMIN" />
    <security:user name="user" password="password" authorities="ROLE_USER" />
   </security:user-service>
  </security:authentication-provider>
 </security:authentication-manager>

</beans>

As according to the above application context file, we want all URLs within our application to be secured, requiring the role ROLE_USER to access them, we want to log in to the application using a form with username and password, and that we want a logout URL registered which will allow us to log out of the application. The configuration above defines two users, their passwords and their roles within the application.

  • <security:http> : This element is the parent for all web-related namespace functionality. It is responsible for creating a FilterChainProxy and the filter beans which it uses. Common problems like incorrect filter ordering are no longer an issue as the filter positions are predefined.
  • <security:intercept-url> : This element defines a pattern which is matched against the URLs of incoming requests using an ant path style syntax.
    • Note: You can use multiple <security:intercept-url> elements to define different access requirements for different sets of URLs, but they will be evaluated in the order listed and the first match will be used. So you must put the most specific matches at the top.
  • <security:authentication-manager> : This element creates a ProviderManager and registers the authentication providers with it.
  • <security:authentication-provider> : This element creates a DaoAuthenticationProvider bean.
  • <security:user-service> : This element creates an InMemoryDaoImpl.

Adding Custom Login Form:
Thus far Spring Security generates login form automatically, based on the features that are enabled and using standard values for the URL which processes the submitted login, the default target URL the user will be sent to after logging in and so on.

<security:http pattern="/login" security="none"/>
<security:http pattern="/css/**" security="none"/>
<security:http pattern="/scripts/**" security="none"/> 
<security:http>
 <security:intercept-url pattern="/**" access="hasRole('USER')" />
 <security:form-login login-page="/login"/>
 <security:logout/>
</security:http>
 
<security:authentication-manager>
 <security:authentication-provider>
  <security:user-service>
   <security:user name="admin" password="adminpassword" authorities="ROLE_USER, ROLE_ADMIN" />
   <security:user name="user" password="password" authorities="ROLE_USER" />
  </security:user-service>
 </security:authentication-provider>
</security:authentication-manager>

From Spring Security 3.1 it is now possible to use multiple http elements to define separate security filter chain configurations for different request patterns. It is also possible to have all requests matching a particular pattern bypass the security filter chain completely, by defining a separate http element for the pattern like this /login, “/resources/”, “/scripts/”, “/css/” etc.

Handling Logouts
When using the <security:logout/>, logout capabilities are automatically applied.
The default is that accessing the URL /logout will log the user out by:

  • Invalidating the HTTP Session
  • Cleaning up any RememberMe authentication that was configured
  • Clearing the SecurityContextHolder
  • Redirect to /login?logout

<security:logout 
    invalidate-session="true" 
    delete-cookies="AppCookies" 
    logout-url="/logout" 
    logout-success-url="/home"/>

Configure Authentication Providers
There are three built in options:

  1. LDAP, 
  2. JDBC, 
  3. in-memory .

In-Memory Authentication Namespace Configuration

<security:authentication-manager>
 <security:authentication-provider>
  <security:user-service>
   <security:user name="admin" password="adminpassword" authorities="ROLE_USER, ROLE_ADMIN" />
   <security:user name="user" password="password" authorities="ROLE_USER" />
  </security:user-service>
 </security:authentication-provider>
</security:authentication-manager>

JDBC Authentication Namespace Configuration

<authentication-manager>
<authentication-provider>
 <jdbc-user-service data-source-ref="dataSource"/>
</authentication-provider>
</authentication-manager>

Where “dataSource” is the name of a DataSource bean in the application context, pointing at a database containing the standard Spring Security user data tables.

Password Encoder
You can also customize how passwords are encoded by exposing a PasswordEncoder as a bean. We can encode passwords using a hash – sha, md5, bcrypt etc.

<security:http pattern="/login" security="none"/>
 <security:http pattern="/css/**" security="none"/>
 <security:http pattern="/scripts/**" security="none"/>
 
 <security:http>
  <security:intercept-url pattern="/**" access="hasRole('USER')" />
  <security:form-login login-page="/login"/>
  <security:logout/>
 </security:http>
 <bean name="bcryptEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
 <security:authentication-manager>
  <security:authentication-provider>
   <security:password-encoder ref="bcryptEncoder"/>
   <security:user-service>
    <security:user name="admin" password="4e7421b1b8765d8f9406d87e7cc6aa784c4ab97f" authorities="ROLE_USER, ROLE_ADMIN" />
    <security:user name="user" password="d7e6351eaa13189a5a3641bab846c8e8c69ba39f" authorities="ROLE_USER" />
   </security:user-service>
  </security:authentication-provider>
 </security:authentication-manager>

Method Security
From Spring version 2.0 Spring Security provides support to adding security to your service layer methods. Spring Security uses AOP for security at the method level.
– annotations based on Spring annotations or JSR-250 annotations
– Java configuration to activate detection of annotations
– From 3.0 you can also make use of new expression-based annotations.
Typically secure your services
– Do not access repositories directly, bypasses security (and transactions)

EnableGlobalMethodSecurity
<global-method-security>- This element is used to enable annotation-based security in your application. The following declaration would enable support for Spring Security’s @Secured:

<global-method-security secured-annotations="enabled" />

import org.springframework.security.annotation.Secured;

public class ItemManagerService {
@Secured("IS_AUTHENTICATED_FULLY")
public Item findItem(long itemNumber) {
...
}
}

We can also use

  • @Secured(“ROLE_MEMBER”)
  • @Secured({“ROLE_MEMBER”, “ROLE_USER”})

Note: Spring 2.0 syntax, so not limited to roles. SpEL not supported.

Enable Method Security – JSR-250
Support for JSR-250 annotations can be enabled using.

<global-method-security jsr250-annotations="enabled" />

import javax.annotation.security.RolesAllowed;

public class ItemManagerService {
@RolesAllowed({"ROLE_MEMBER", "ROLE_USER"})
public Item findItem(long itemNumber) {
...
}
}

Note: Only supports role-based security – hence the name

Method Security with SpEL
To use the new expression-based syntax, you would use

<global-method-security pre-post-annotations="enabled" />

public interface ItemManagerService {

@PreAuthorize("isAnonymous()")
public Item findItem(Long itemNumber);

@PreAuthorize("isAnonymous()")
public Item[] findItems();

@PreAuthorize("hasAuthority('ROLE_USER')")
public Item post(Item item);
}

Adding Security Pointcuts using protect-pointcut
The use of protect-pointcut is particularly powerful, as it allows you to apply security to many beans with only a simple declaration. Consider the following example:

<global-method-security>
<protect-pointcut expression="execution(* com.doj.app.*Service.*(..))"
 access="ROLE_USER"/>
</global-method-security>

This will protect all methods on beans declared in the application context whose classes are in the com.doj.app package and whose class names end in “Service“. Only users with the ROLE_USER role will be able to invoke these methods.

Download Java Based Configuration Example from Git

Spring Security XML Namespace Configuration Example