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.
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 spring-security-core-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 Spring 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/springframework/security/messages"/> </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)
Spring Security uses many filters, as referred to throughout the remainder of this reference guide. If you are using namespace configuration, then the you don't usually have to declare the filter beans explicitly. There may be times when you want full control over the security filter chain, either because you are using features which aren't supported in the namespace, or you are using your own customized versions of classes.
In this case, you have a choice in how these filters are added to your web application, in that you can use either
Spring's DelegatingFilterProxy
or
FilterChainProxy
. We'll look at both below.
When using DelegatingFilterProxy
, you will see
something like this in the web.xml file:
<filter> <filter-name>myFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>myFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
Notice that the filter is actually a DelegatingFilterProxy
,
and not the filter that will actually implement the logic of the filter. What
DelegatingFilterProxy
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 web application context lifecycle support and
configuration flexibility. The bean must implement
javax.servlet.Filter
and it must have the same name as that in
the filter-name
element.
There is a lifecycle issue to consider when hosting
Filter
s 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. Read the Javadoc for DelegatingFilterProxy
for more information
Rather than using DelegatingFilterProxy
, we
strongly recommend that you use FilterChainProxy
instead.
Whilst DelegatingFilterProxy
is a very useful class,
the problem is that the number of 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
DelegatingFilterProxy
(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"> <sec:filter-chain-map path-type="ant"> <sec:filter-chain pattern="/webServices/**" filters="httpSessionContextIntegrationFilterWithASCFalse,basicProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor"/> <sec:filter-chain pattern="/**" filters="httpSessionContextIntegrationFilterWithASCTrue,authenticationProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor"/> </sec:filter-chain-map> </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 and the list
of filter beans specified by the filters
attribute
will be applied to that request. The filters will be invoked in the order
they are defined, so you have complete control over the filter chain
which is applied to a particular URL.
You may have noticed we have declared two
HttpSessionContextIntegrationFilter
s 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 HttpSession
s 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 Filter
s 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
targetFilterLifecycle
initialization parameter of the
DelegatingFilterProxy
that proxies
DelegatingFilterProxy
. As discussed above, by default
any servlet container lifecycle invocations are not delegated through
to DelegatingFilterProxy
.
You can use the attribute filters = "none"
in the same way that you do when using namespace configuration
to build the FilterChainProxy
. This will omit the
request pattern from the security filter chain entirely.
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
DelegatingFilterProxy
or
FilterChainProxy
. It is recommended that a single
DelegatingFilterProxy
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
Spring Security comes bundled with several JSP tag libraries which provide a range of different services.
All taglib classes are included in the core
spring-security-xx.jar
file, with the
security.tld
located in the JAR's
META-INF
directory. This means for JSP 1.2+ web
containers you can simply include the JAR in the WAR's
WEB-INF/lib
directory and it will be available. If
you're using a JSP 1.1 container, you'll need to declare the JSP
taglib in your web.xml file
, and include
security.tld
in the WEB-INF/lib
directory. The following fragment is added to
web.xml
:
<taglib> <taglib-uri>http://www.springframework.org/security/tags</taglib-uri> <taglib-location>/WEB-INF/security.tld</taglib-location> </taglib>
Now that you've configured the tag libraries, refer to the individual reference guide sections for details on how to use them. Note that when using the tags, you should include the taglib reference in your JSP:
<%@ taglib prefix='security' uri='http://www.springframework.org/security/tags' %>