Supporting Infrastructure This chapter introduces some of the supplementary and supporting infrastructure used by Spring Security. If a capability is not directly related to security, yet included in the Spring Security project, we will discuss it in this chapter. Localization Spring Security supports localization of exception messages that end users are likely to see. If your application is designed for English users, you don't need to do anything as by default all Security Security messages are in English. If you need to support other locales, everything you need to know is contained in this section. All exception messages can be localized, including messages related to authentication failures and access being denied (authorization failures). Exceptions and logging that is focused on developers or system deployers (including incorrect attributes, interface contract violations, using incorrect constructors, startup time validation, debug-level logging) etc are not localized and instead are hard-coded in English within Spring Security's code. Shipping in the acegi-security-xx.jar you will find an org.springframework.security package that in turn contains a messages.properties file. This should be referred to by your ApplicationContext, as Acegi Security classes implement Spring's MessageSourceAware interface and expect the message resolver to be dependency injected at application context startup time. Usually all you need to do is register a bean inside your application context to refer to the messages. An example is shown below: <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <property name="basename"><value>org/acegisecurity/messages</value></property> </bean> The messages.properties is named in accordance with standard resource bundles and represents the default language supported by Spring Security messages. This default file is in English. If you do not register a message source, Spring Security will still work correctly and fallback to hard-coded English versions of the messages. If you wish to customize the messages.properties file, or support other languages, you should copy the file, rename it accordingly, and register it inside the above bean definition. There are not a large number of message keys inside this file, so localization should not be considered a major initiative. If you do perform localization of this file, please consider sharing your work with the community by logging a JIRA task and attaching your appropriately-named localized version of messages.properties. Rounding out the discussion on localization is the Spring ThreadLocal known as org.springframework.context.i18n.LocaleContextHolder. You should set the LocaleContextHolder to represent the preferred Locale of each user. Spring Security will attempt to locate a message from the message source using the Locale obtained from this ThreadLocal. Please refer to Spring documentation for further details on using LocaleContextHolder and the helper classes that can automatically set it for you (eg AcceptHeaderLocaleResolver, CookieLocaleResolver, FixedLocaleResolver, SessionLocaleResolver etc) Filters Spring Security uses many filters, as referred to throughout the remainder of this reference guide. You have a choice in how these filters are added to your web application, in that you can use either FilterToBeanProxy or FilterChainProxy. We'll look at both below. Most filters are configured using the FilterToBeanProxy. An example configuration from web.xml follows: <filter> <filter-name>Spring Security HTTP Request Security Filter</filter-name> <filter-class>org.springframework.security.util.FilterToBeanProxy</filter-class> <init-param> <param-name>targetClass</param-name> <param-value>org.springframework.security.ClassThatImplementsFilter</param-value> </init-param> </filter> Notice that the filter in web.xml is actually a FilterToBeanProxy, and not the filter that will actually implement the logic of the filter. What FilterToBeanProxy does is delegate the Filter's methods through to a bean which is obtained from the Spring application context. This enables the bean to benefit from the Spring application context lifecycle support and configuration flexibility. The bean must implement javax.servlet.Filter. The FilterToBeanProxy only requires a single initialization parameter, targetClass or targetBean. The targetClass parameter locates the first object in the application context of the specified class, whilst targetBean locates the object by bean name. Like standard Spring web applications, the FilterToBeanProxy accesses the application context via WebApplicationContextUtils.getWebApplicationContext(ServletContext), so you should configure a ContextLoaderListener in web.xml. There is a lifecycle issue to consider when hosting Filters in an IoC container instead of a servlet container. Specifically, which container should be responsible for calling the Filter's "startup" and "shutdown" methods? It is noted that the order of initialization and destruction of a Filter can vary by servlet container, and this can cause problems if one Filter depends on configuration settings established by an earlier initialized Filter. The Spring IoC container on the other hand has more comprehensive lifecycle/IoC interfaces (such as InitializingBean, DisposableBean, BeanNameAware, ApplicationContextAware and many others) as well as a well-understood interface contract, predictable method invocation ordering, autowiring support, and even options to avoid implementing Spring interfaces (eg the destroy-method attribute in Spring XML). For this reason we recommend the use of Spring lifecycle services instead of servlet container lifecycle services wherever possible. By default FilterToBeanProxy will not delegate init(FilterConfig) and destroy() methods through to the proxied bean. If you do require such invocations to be delegated, set the lifecycle initialization parameter to servlet-container-managed. Rather than using FilterToBeanProxy, we strongly recommend to use FilterChainProxy instead. Whilst FilterToBeanProxy is a very useful class, the problem is that the lines of code required for <filter> and <filter-mapping> entries in web.xml explodes when using more than a few filters. To overcome this issue, Spring Security provides a FilterChainProxy class. It is wired using a FilterToBeanProxy (just like in the example above), but the target class is org.springframework.security.util.FilterChainProxy. The filter chain is then declared in the application context, using code such as this: <bean id="filterChainProxy" class="org.springframework.security.util.FilterChainProxy"> <property name="filterInvocationDefinitionSource"> <value> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /webServices/**=httpSessionContextIntegrationFilterWithASCFalse,basicProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor /**=httpSessionContextIntegrationFilterWithASCTrue,authenticationProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor </value> </property> </bean> You may notice similarities with the way FilterSecurityInterceptor is declared. Both regular expressions and Ant Paths are supported, and the most specific URIs appear first. At runtime the FilterChainProxy will locate the first URI pattern that matches the current web request. Each of the corresponding configuration attributes represent the name of a bean defined in the application context. The filters will then be invoked in the order they are specified, with standard FilterChain behaviour being respected (a Filter can elect not to proceed with the chain if it wishes to end processing). As you can see, FilterChainProxy requires the duplication of filter names for different request patterns (in the above example, exceptionTranslationFilter and filterSecurityInterceptor are duplicated). This design decision was made to enable FilterChainProxy to specify different Filter invocation orders for different URI patterns, and also to improve both the expressiveness (in terms of regular expressions, Ant Paths, and any custom FilterInvocationDefinitionSource implementations) and clarity of which Filters should be invoked. You may have noticed we have declared two HttpSessionContextIntegrationFilters in the filter chain (ASC is short for allowSessionCreation, a property of HttpSessionContextIntegrationFilter). As web services will never present a jsessionid on future requests, creating HttpSessions for such user agents would be wasteful. If you had a high-volume application which required maximum scalability, we recommend you use the approach shown above. For smaller applications, using a single HttpSessionContextIntegrationFilter (with its default allowSessionCreation as true) would likely be sufficient. In relation to lifecycle issues, the FilterChainProxy will always delegate init(FilterConfig) and destroy() methods through to the underlaying Filters if such methods are called against FilterChainProxy itself. In this case, FilterChainProxy guarantees to only initialize and destroy each Filter once, irrespective of how many times it is declared by the FilterInvocationDefinitionSource. You control the overall choice as to whether these methods are called or not via the lifecycle initialization parameter of the FilterToBeanProxy that proxies FilterChainProxy. As discussed above, by default any servlet container lifecycle invocations are not delegated through to FilterChainProxy. You can also omit a URI pattern from the filter chain by using the token #NONE# on the right-hand side of the <URI Pattern> = <Filter Chain> expression. For example, using the example above, if you wanted to exclude the /webservices location completely, you would modify the corresponding line in the bean declaration to be /webServices/**=#NONE# Note that anything matching this path will then have no authentication or authorization services applied and will be freely accessible. The order that filters are defined in web.xml is very important. Irrespective of which filters you are actually using, the order of the <filter-mapping>s should be as follows: ChannelProcessingFilter, because it might need to redirect to a different protocol ConcurrentSessionFilter, because it doesn't use any SecurityContextHolder functionality but needs to update the SessionRegistry to reflect ongoing requests from the principal HttpSessionContextIntegrationFilter, so a SecurityContext can be setup in the SecurityContextHolder at the beginning of a web request, and any changes to the SecurityContext can be copied to the HttpSession when the web request ends (ready for use with the next web request) Authentication processing mechanisms - AuthenticationProcessingFilter, CasProcessingFilter, BasicProcessingFilter, HttpRequestIntegrationFilter, JbossIntegrationFilter etc - so that the SecurityContextHolder can be modified to contain a valid Authentication request token The SecurityContextHolderAwareRequestFilter, if you are using it to install a Spring Security aware HttpServletRequestWrapper into your servlet container RememberMeProcessingFilter, so that if no earlier authentication processing mechanism updated the SecurityContextHolder, and the request presents a cookie that enables remember-me services to take place, a suitable remembered Authentication object will be put there AnonymousProcessingFilter, so that if no earlier authentication processing mechanism updated the SecurityContextHolder, an anonymous Authentication object will be put there ExceptionTranslationFilter, to catch any Spring Security exceptions so that either an HTTP error response can be returned or an appropriate AuthenticationEntryPoint can be launched FilterSecurityInterceptor, to protect web URIs All of the above filters use FilterToBeanProxy or FilterChainProxy. It is recommended that a single FilterToBeanProxy proxy through to a single FilterChainProxy for each application, with that FilterChainProxy defining all of Spring Security Filters. If you're using SiteMesh, ensure Spring Security filters execute before the SiteMesh filters are called. This enables the SecurityContextHolder to be populated in time for use by SiteMesh decorators