mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-05-31 09:12:14 +00:00
342 lines
18 KiB
XML
342 lines
18 KiB
XML
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="supporting-infrastructure" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
|
|
<info><title>Supporting Infrastructure</title></info>
|
|
|
|
|
|
<para>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.</para>
|
|
|
|
<section xml:id="localization">
|
|
<title>Localization</title>
|
|
<para>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.</para>
|
|
|
|
<para>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.</para>
|
|
|
|
<para>Shipping in the <literal>spring-security-core-xx.jar</literal> you
|
|
will find an <literal>org.springframework.security</literal> package
|
|
that in turn contains a <literal>messages.properties</literal> file.
|
|
This should be referred to by your
|
|
<literal>ApplicationContext</literal>, as Spring Security classes
|
|
implement Spring's <literal>MessageSourceAware</literal> 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:</para>
|
|
|
|
<para><programlisting><![CDATA[
|
|
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
|
|
<property name="basename" value="org/springframework/security/messages"/>
|
|
</bean>
|
|
]]></programlisting></para>
|
|
|
|
<para>The <literal>messages.properties</literal> 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.</para>
|
|
|
|
<para>If you wish to customize the
|
|
<literal>messages.properties</literal> 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 <literal>messages.properties</literal>.</para>
|
|
|
|
<para>Rounding out the discussion on localization is the Spring
|
|
<literal>ThreadLocal</literal> known as
|
|
<literal>org.springframework.context.i18n.LocaleContextHolder</literal>.
|
|
You should set the <literal>LocaleContextHolder</literal> to represent
|
|
the preferred <literal>Locale</literal> of each user. Spring Security
|
|
will attempt to locate a message from the message source using the
|
|
<literal>Locale</literal> obtained from this
|
|
<literal>ThreadLocal</literal>. Please refer to Spring documentation
|
|
for further details on using <literal>LocaleContextHolder</literal>
|
|
and the helper classes that can automatically set it for you (eg
|
|
<literal>AcceptHeaderLocaleResolver</literal>,
|
|
<literal>CookieLocaleResolver</literal>,
|
|
<literal>FixedLocaleResolver</literal>,
|
|
<literal>SessionLocaleResolver</literal> etc)</para>
|
|
</section>
|
|
|
|
<section xml:id="filters">
|
|
<info><title>Filters</title></info>
|
|
|
|
<para>Spring Security uses many filters, as referred to throughout the
|
|
remainder of this reference guide. If you are using <link xlink:href="#ns-config">namespace configuration</link>,
|
|
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.</para>
|
|
<para>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 <literal>DelegatingFilterProxy</literal> or
|
|
<classname>FilterChainProxy</classname>. We'll look at both below.</para>
|
|
|
|
<para>When using <literal>DelegatingFilterProxy</literal>, you will see
|
|
something like this in the web.xml file:
|
|
|
|
<programlisting>
|
|
<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>
|
|
</programlisting>
|
|
|
|
Notice that the filter is actually a <literal>DelegatingFilterProxy</literal>,
|
|
and not the filter that will actually implement the logic of the filter. What
|
|
<literal>DelegatingFilterProxy</literal> does is delegate the
|
|
<literal>Filter</literal>'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
|
|
<literal>javax.servlet.Filter</literal> and it must have the same name as that in
|
|
the <literal>filter-name</literal> element.</para>
|
|
|
|
<para>There is a lifecycle issue to consider when hosting
|
|
<literal>Filter</literal>s in an IoC container instead of a servlet
|
|
container. Specifically, which container should be responsible for
|
|
calling the <literal>Filter</literal>'s "startup" and "shutdown"
|
|
methods? It is noted that the order of initialization and destruction
|
|
of a <literal>Filter</literal> can vary by servlet container, and this
|
|
can cause problems if one <literal>Filter</literal> depends on
|
|
configuration settings established by an earlier initialized
|
|
<literal>Filter</literal>. The Spring IoC container on the other hand
|
|
has more comprehensive lifecycle/IoC interfaces (such as
|
|
<literal>InitializingBean</literal>,
|
|
<literal>DisposableBean</literal>, <literal>BeanNameAware</literal>,
|
|
<literal>ApplicationContextAware</literal> 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 <literal>destroy-method</literal> 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 <classname>DelegatingFilterProxy</classname>
|
|
for more information</para>
|
|
|
|
<para>Rather than using <literal>DelegatingFilterProxy</literal>, we
|
|
strongly recommend that you use <classname>FilterChainProxy</classname> instead.
|
|
Whilst <literal>DelegatingFilterProxy</literal> is a very useful class,
|
|
the problem is that the number of lines of code required for
|
|
<literal><filter></literal> and
|
|
<literal><filter-mapping></literal> entries in
|
|
<literal>web.xml</literal> explodes when using more than a few
|
|
filters. To overcome this issue, Spring Security provides a
|
|
<classname>FilterChainProxy</classname> class. It is wired using a
|
|
<literal>DelegatingFilterProxy</literal> (just like in the example above),
|
|
but the target class is
|
|
<literal>org.springframework.security.web.FilterChainProxy</literal>.
|
|
The filter chain is then declared in the application context, using
|
|
code such as this:</para>
|
|
|
|
<para><programlisting><![CDATA[
|
|
<bean id="filterChainProxy" class="org.springframework.security.web.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>
|
|
]]>
|
|
</programlisting></para>
|
|
|
|
<para>You may notice similarities with the way
|
|
<classname>FilterSecurityInterceptor</classname> is declared. Both regular
|
|
expressions and Ant Paths are supported, and the most specific URIs
|
|
appear first. At runtime the <classname>FilterChainProxy</classname> will
|
|
locate the first URI pattern that matches the current web request and the list
|
|
of filter beans specified by the <literal>filters</literal> 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.</para>
|
|
|
|
<para>You may have noticed we have declared two
|
|
<classname>HttpSessionContextIntegrationFilter</classname>s in the filter
|
|
chain (<literal>ASC</literal> is short for
|
|
<literal>allowSessionCreation</literal>, a property of
|
|
<classname>HttpSessionContextIntegrationFilter</classname>). As web
|
|
services will never present a <literal>jsessionid</literal> on future
|
|
requests, creating <literal>HttpSession</literal>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
|
|
<classname>HttpSessionContextIntegrationFilter</classname> (with its
|
|
default <literal>allowSessionCreation</literal> as
|
|
<literal>true</literal>) would likely be sufficient.</para>
|
|
|
|
<para>In relation to lifecycle issues, the
|
|
<classname>FilterChainProxy</classname> will always delegate
|
|
<literal>init(FilterConfig)</literal> and <literal>destroy()</literal>
|
|
methods through to the underlaying <literal>Filter</literal>s if such
|
|
methods are called against <classname>FilterChainProxy</classname> itself.
|
|
In this case, <classname>FilterChainProxy</classname> guarantees to only
|
|
initialize and destroy each <literal>Filter</literal> once,
|
|
irrespective of how many times it is declared by the
|
|
<interfacename>FilterInvocationDefinitionSource</interfacename>. You control the
|
|
overall choice as to whether these methods are called or not via the
|
|
<literal>targetFilterLifecycle</literal> initialization parameter of the
|
|
<literal>DelegatingFilterProxy</literal> that proxies
|
|
<literal>DelegatingFilterProxy</literal>. As discussed above, by default
|
|
any servlet container lifecycle invocations are not delegated through
|
|
to <literal>DelegatingFilterProxy</literal>.</para>
|
|
|
|
<para>You can use the attribute <literal>filters = "none"</literal>
|
|
in the same way that you do when using <link xlink:href="#namespace-auto-config">namespace configuration</link>
|
|
to build the <classname>FilterChainProxy</classname>. 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.</para>
|
|
|
|
<para>The order that filters are defined in <literal>web.xml</literal>
|
|
is very important. Irrespective of which filters you are actually
|
|
using, the order of the <literal><filter-mapping></literal>s
|
|
should be as follows:</para>
|
|
|
|
<orderedlist inheritnum="ignore" continuation="restarts">
|
|
<listitem>
|
|
<para><literal>ChannelProcessingFilter</literal>, because it might
|
|
need to redirect to a different protocol</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>ConcurrentSessionFilter</literal>, because it
|
|
doesn't use any <classname>SecurityContextHolder</classname>
|
|
functionality but needs to update the
|
|
<interfacename>SessionRegistry</interfacename> to reflect ongoing requests
|
|
from the principal</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><classname>HttpSessionContextIntegrationFilter</classname>, so a
|
|
<interfacename>SecurityContext</interfacename> can be setup in the
|
|
<classname>SecurityContextHolder</classname> at the beginning of a web
|
|
request, and any changes to the <interfacename>SecurityContext</interfacename>
|
|
can be copied to the <literal>HttpSession</literal> when the web
|
|
request ends (ready for use with the next web request)</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Authentication processing mechanisms -
|
|
<literal>UsernamePasswordAuthenticationProcessingFilter</literal>,
|
|
<literal>CasProcessingFilter</literal>,
|
|
<literal>BasicProcessingFilter, HttpRequestIntegrationFilter,
|
|
JbossIntegrationFilter</literal> etc - so that the
|
|
<classname>SecurityContextHolder</classname> can be modified to
|
|
contain a valid <interfacename>Authentication</interfacename> request
|
|
token</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>The
|
|
<literal>SecurityContextHolderAwareRequestFilter</literal>, if you
|
|
are using it to install a Spring Security aware
|
|
<literal>HttpServletRequestWrapper</literal> into your servlet
|
|
container</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><classname>RememberMeProcessingFilter</classname>, so that if no
|
|
earlier authentication processing mechanism updated the
|
|
<classname>SecurityContextHolder</classname>, and the request presents
|
|
a cookie that enables remember-me services to take place, a
|
|
suitable remembered
|
|
<interfacename>Authentication</interfacename> object will
|
|
be put there</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>AnonymousProcessingFilter</literal>, so that if no
|
|
earlier authentication processing mechanism updated the
|
|
<classname>SecurityContextHolder</classname>, an anonymous
|
|
<interfacename>Authentication</interfacename> object will be put there</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><classname>ExceptionTranslationFilter</classname>, to catch any
|
|
Spring Security exceptions so that either an HTTP error response
|
|
can be returned or an appropriate
|
|
<interfacename>AuthenticationEntryPoint</interfacename> can be launched</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><classname>FilterSecurityInterceptor</classname>, to protect web
|
|
URIs</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
|
|
<para>All of the above filters use
|
|
<literal>DelegatingFilterProxy</literal> or
|
|
<classname>FilterChainProxy</classname>. It is recommended that a single
|
|
<literal>DelegatingFilterProxy</literal> proxy through to a single
|
|
<classname>FilterChainProxy</classname> for each application, with that
|
|
<classname>FilterChainProxy</classname> defining all of Spring Security
|
|
filters.</para>
|
|
|
|
<para>If you're using SiteMesh, ensure Spring Security filters execute
|
|
before the SiteMesh filters are called. This enables the
|
|
<classname>SecurityContextHolder</classname> to be populated in time for
|
|
use by SiteMesh decorators</para>
|
|
</section>
|
|
|
|
<section xml:id="taglib">
|
|
<info><title>Tag Libraries</title></info>
|
|
|
|
<para>Spring Security comes bundled with several JSP tag libraries which provide a range of different
|
|
services.</para>
|
|
|
|
<section xml:id="taglib-config">
|
|
<info><title>Configuration</title></info>
|
|
<para>All taglib classes are included in the core
|
|
<literal>spring-security-xx.jar</literal> file, with the
|
|
<literal>security.tld</literal> located in the JAR's
|
|
<literal>META-INF</literal> directory. This means for JSP 1.2+ web
|
|
containers you can simply include the JAR in the WAR's
|
|
<literal>WEB-INF/lib</literal> 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 <literal>web.xml file</literal>, and include
|
|
<literal>security.tld</literal> in the <literal>WEB-INF/lib</literal>
|
|
directory. The following fragment is added to
|
|
<literal>web.xml</literal>:
|
|
<programlisting><![CDATA[
|
|
<taglib>
|
|
<taglib-uri>http://www.springframework.org/security/tags</taglib-uri>
|
|
<taglib-location>/WEB-INF/security.tld</taglib-location>
|
|
</taglib>
|
|
]]></programlisting></para>
|
|
</section>
|
|
|
|
<section xml:id="taglib-usage">
|
|
<info><title>Usage</title></info>
|
|
<para>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:
|
|
<programlisting>
|
|
<%@ taglib prefix='security' uri='http://www.springframework.org/security/tags' %>
|
|
|
|
</programlisting></para>
|
|
</section>
|
|
</section>
|
|
</chapter> |