Advanced Web Features

Remember-Me Authentication

See the separate Remember-Me chapter for information on remember-me namespace configuration.

Adding HTTP/HTTPS Channel Security

If your application supports both HTTP and HTTPS, and you require that particular URLs can only be accessed over HTTPS, then this is directly supported using the requires-channel attribute on <intercept-url>:

  <http>
    <intercept-url pattern="/secure/**" access="ROLE_USER" requires-channel="https"/>
    <intercept-url pattern="/**" access="ROLE_USER" requires-channel="any"/>  
    ...
  </http>
        

With this configuration in place, if a user attempts to access anything matching the "/secure/**" pattern using HTTP, they will first be redirected to an HTTPS URL. The available options are "http", "https" or "any". Using the value "any" means that either HTTP or HTTPS can be used.

If your application uses non-standard ports for HTTP and/or HTTPS, you can specify a list of port mappings as follows:

        
               
  <http>
    ...
    <port-mappings>
      <port-mapping http="9080" https="9443"/>
    </port-mappings>
  </http>
        

You can find a more in-depth discussion of channel security in Chapter 7, Channel Security.

Concurrent Session Control

If you wish to place constraints on a single user's ability to log in to your application, Spring Security supports this out of the box with the following simple additions. First you need to add the following listener to your web.xml file to keep Spring Security updated about session lifecycle events:

        
                   
<listener>
  <listener-class>org.springframework.security.ui.session.HttpSessionEventPublisher</listener-class>
</listener>

Then add the following line to your application context:

     
  <http>
    ...
    <concurrent-session-control max-sessions="1" />
  </http>
        

This will prevent a user from logging in multiple times - a second login will cause the first to be invalidated. Often you would prefer to prevent a second login, in which case you can use

     
  <http>
    ...
    <concurrent-session-control max-sessions="1" exception-if-maximum-exceeded="true"/>
  </http>
        

The second login will then be rejected.

OpenID Login

The namespace supports OpenID login either instead of, or in addition to normal form-based login, with a simple change:

  <http>
    <intercept-url pattern="/**" access="ROLE_USER" />
    <openid-login />
  </http>
  

You should then register yourself with an OpenID provider (such as myopenid.com), and add the user information to your in-memory <user-service>:

  <user name="http://jimi.hendrix.myopenid.com/" password="notused" authorities="ROLE_USER" />
  

You should be able to login using the myopenid.com site to authenticate.

Adding in Your Own Filters

If you've used Spring Security before, you'll know that the framework maintains a chain of filters in order to apply its services. You may want to add your own filters to the stack at particular locations or use a Spring Security filter for which there isn't currently a namespace configuration option (CAS, for example). Or you might want to use a customized version of a standard namespace filter, such as the AuthenticationProcessingFilter which is created by the <form-login> element, taking advantage of some of the extra configuration options which are available by using defining the bean directly. How can you do this with namespace configuration, since the filter chain is not directly exposed?

The order of the filters is always strictly enforced when using the namespace. Each Spring Security filter implements the Spring Ordered interface and the filters created by the namespace are sorted during initialization. The standard Spring Security filters each have an alias in the namespace. The filters, aliases and namespace elements/attributes which create the filters are shown in Table 2.1, “Standard Filter Aliases and Ordering”.

Table 2.1. Standard Filter Aliases and Ordering

AliasFilter ClassNamespace Element or Attribute
CHANNEL_FILTERChannelProcessingFilterhttp/intercept-url
CONCURRENT_SESSION_FILTERConcurrentSessionFilter http/concurrent-session-control
SESSION_CONTEXT_INTEGRATION_FILTERHttpSessionContextIntegrationFilterhttp
LOGOUT_FILTER LogoutFilterhttp/logout
X509_FILTER X509PreAuthenticatedProcessigFilterhttp/x509
PRE_AUTH_FILTER AstractPreAuthenticatedProcessingFilter SubclassesN/A
CAS_PROCESSING_FILTER CasProcessingFilterN/A
AUTHENTICATION_PROCESSING_FILTER AuthenticationProcessingFilterhttp/form-login
BASIC_PROCESSING_FILTER BasicProcessingFilterhttp/http-basic
SERVLET_API_SUPPORT_FILTERSecurityContextHolderAwareRequestFilterhttp/@servlet-api-provision
REMEMBER_ME_FILTER RememberMeProcessingFilterhttp/remember-me
ANONYMOUS_FILTER AnonymousProcessingFilterhttp/anonymous
EXCEPTION_TRANSLATION_FILTER ExceptionTranslationFilterhttp
NTLM_FILTER NtlmProcessingFilterN/A
FILTER_SECURITY_INTERCEPTOR FilterSecurityInterceptorhttp
SWITCH_USER_FILTER SwitchUserProcessingFilterN/A


You can add your own filter to the stack, using the custom-filter element and one of these names to specify the position your filter should appear at:

  <beans:bean id="myFilter" class="com.mycompany.MySpecialAuthenticationFilter">
    <custom-filter position="AUTHENTICATION_PROCESSING_FILTER"/>
  </beans:bean>
  

You can also use the after or before attribtues if you want your filter to be inserted before or after another filter in the stack. The names "FIRST" and "LAST" can be used with the position attribute to indicate that you want your filter to appear before or after the entire stack, respectively.

Avoiding filter position conflicts

If you are inserting a custom filter which may occupy the same position as one of the standard filters created by the namespace then it's important that you don't include the namespace versions by mistake. Avoid using the auto-config attribute and remove any elements which create filters whose functionality you want to replace.

Note that you can't replace filters which are created by the use of the <http> element itself - HttpSessionContextIntegrationFilter, ExceptionTranslationFilter or FilterSecurityInterceptor.

If you're replacing a namespace filter which requires an authentication entry point (i.e. where the authentication process is triggered by an attempt by an unauthenticated user to access to a secured resource), you will need to add a custom entry point bean too.

Setting a Custom AuthenticationEntryPoint

If you aren't using form login, OpenID or basic authentication through the namespace, you may want to define an authentication filter and entry point using a traditional bean syntax and link them into the namespace, as we've just seen. The corresponding AuthenticationEntryPoint can be set using the entry-point-ref attribute on the <http> element.

The CAS sample application is a good example of the use of custom beans with the namespace, including this syntax. If you aren't familiar with authentication entry points, they are discussed in the technical overview chapter.

Session Fixation Attack Protection

Session fixation attacks are a potential risk where it is possible for a malicious attacker to create a session by accessing a site, then persuade another user to log in with the same session (by sending them a link containing the session identifier as a parameter, for example). Spring Security protects against this automatically by creating a new session when a user logs in. If you don't require this protection, or it conflicts with some other requirement, you can control the behaviour using the session-fixation-protection attribute on <http>, which has three options

  • migrateSession - creates a new session and copies the existing session attributes to the new session. This is the default.

  • none - Don't do anything. The original session will be retained.

  • newSession - Create a new "clean" session, without copying the existing session data.