|
@@ -1,97 +1,32 @@
|
|
|
-<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="supporting-infrastructure" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
|
+<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="web-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>
|
|
|
+ <info><title>Web Security Infrastructure</title></info>
|
|
|
|
|
|
<section xml:id="filters">
|
|
|
- <info><title>Filters</title></info>
|
|
|
+ <title>Spring Security Filters</title>
|
|
|
|
|
|
- <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:
|
|
|
-
|
|
|
+ <para>Spring Security's web application features are implemented using standard servlet filters. It doesn't use
|
|
|
+ servlets or any other servlet-based frameworks (such as Spring MVC) internally. So it has no strong links to any
|
|
|
+ particular web technology - it deals in <classname>HttpServletRequest</classname>s and <classname>HttpServletResponse</classname>s
|
|
|
+ and doesn't care whether the requests come from a browser, a web service client, an <classname>HttpInvoker</classname> or an AJAX application.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Spring Security maintains a filter chain internally where each of the filters has a particular responsibility and filters are added or removed
|
|
|
+ depending on which services are required. The ordering of the filters is important as there are dependencies between them.
|
|
|
+ If you have been using <link xlink:href="#ns-config">namespace configuration</link>, then the filters are automatically configured for you
|
|
|
+ and you don't have to define any Spring beans explicitly but here 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>
|
|
|
+
|
|
|
+ <section xml:id="delegating-filter-proxy">
|
|
|
+ <title><classname>DelegatingFilterProxy</classname></title>
|
|
|
+ <para>
|
|
|
+ When using servlet filters, you obviously need to declare them in your <filename>web.xml</filename>, or they will be ignored
|
|
|
+ by the servlet container. In Spring Security, the filter classes are also Spring beans defined in the application context and thus able
|
|
|
+ to take advantage of Spring's rich dependency-injection facilities and lifecycle interfaces. Spring's <classname>DelegatingFilterProxy</classname>
|
|
|
+ provides the link between <filename>web.xml</filename> and the application context.
|
|
|
+ </para>
|
|
|
+ <para>When using <classname>DelegatingFilterProxy</classname>, you will see something like this in the <filename>web.xml</filename> file:
|
|
|
+
|
|
|
<programlisting><![CDATA[
|
|
|
<filter>
|
|
|
<filter-name>myFilter</filter-name>
|
|
@@ -103,132 +38,111 @@
|
|
|
<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[
|
|
|
+ Notice that the filter is actually a <literal>DelegatingFilterProxy</literal>,
|
|
|
+ and not the class that will actually implement the logic of the filter. What
|
|
|
+ <classname>DelegatingFilterProxy</classname> does is delegate the
|
|
|
+ <interfacename>Filter</interfacename>'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
|
|
|
+ <interfacename>javax.servlet.Filter</interfacename> and it must have the same name as that in
|
|
|
+ the <literal>filter-name</literal> element. Read the Javadoc for <classname>DelegatingFilterProxy</classname>
|
|
|
+ for more information</para>
|
|
|
+ </section>
|
|
|
+ <section xml:id="filter-chain-proxy">
|
|
|
+ <title><classname>FilterChainProxy</classname></title>
|
|
|
+ <para>
|
|
|
+ It should now be clear that you can declare each Spring Security filter bean that you require in your application context file and add a corresponding
|
|
|
+ <classname>DelegatingFilterProxy</classname> entry to <filename>web.xml</filename> for each filter, making sure that they are ordered correctly.
|
|
|
+ This is a cumbersome approach and clutters up the <filename>web.xml</filename> file quickly if we have a lot of filters. We would prefer to just add
|
|
|
+ a single entry to <filename>web.xml</filename> and deal entirely with the application context file for managing our web security beans.
|
|
|
+ This is where Spring Secuiryt's <classname>FilterChainProxy</classname> comes in. It is wired using a <literal>DelegatingFilterProxy</literal>
|
|
|
+ (just like in the example above), but the target class is <classname>org.springframework.security.web.FilterChainProxy</classname>.
|
|
|
+ The filter chain is then declared in the application context. Here's an example:
|
|
|
+ <programlisting language="xml"><![CDATA[
|
|
|
<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
|
|
|
<sec:filter-chain-map path-type="ant">
|
|
|
<sec:filter-chain pattern="/webServices/**" filters="
|
|
|
- httpSessionContextIntegrationFilterWithASCFalse,
|
|
|
+ securityContextPersistenceFilterWithASCFalse,
|
|
|
basicProcessingFilter,
|
|
|
exceptionTranslationFilter,
|
|
|
filterSecurityInterceptor" />
|
|
|
<sec:filter-chain pattern="/**" filters="
|
|
|
- httpSessionContextIntegrationFilterWithASCTrue,
|
|
|
+ securityContextPersistenceFilterWithASCTrue,
|
|
|
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>
|
|
|
+ </programlisting>
|
|
|
+ The namespace element <literal>filter-chain-map</literal> is used to set up the security filter chain(s) which are required
|
|
|
+ within the application. It maps a particular URL pattern to a chain of filters built up from the bean names
|
|
|
+ specified in the <literal>filters</literal> element. 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>SecurityContextPersistenceFilter</classname>s in the filter
|
|
|
+ chain (<literal>ASC</literal> is short for
|
|
|
+ <literal>allowSessionCreation</literal>, a property of
|
|
|
+ <classname>SecurityContextPersistenceFilter</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>SecurityContextPersistenceFilter</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
|
|
|
+ <methodname>init(FilterConfig)</methodname> and <methodname>destroy()</methodname>
|
|
|
+ methods through to the underlaying <interfacename>Filter</interfacename>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> bean once,
|
|
|
+ no matter how many times it is declared in the filter chain(s). You control the
|
|
|
+ overall choice as to whether these methods are called or not via the
|
|
|
+ <literal>targetFilterLifecycle</literal> initialization parameter of
|
|
|
+ <literal>DelegatingFilterProxy</literal>. By default this property
|
|
|
+ is <literal>false</literal> and servlet container lifecycle invocations are not delegated through
|
|
|
+ <literal>DelegatingFilterProxy</literal>.</para>
|
|
|
+ <para>
|
|
|
+ When we looked at how to set up web security using <link xlink:href="#namespace-auto-config">namespace configuration</link>,
|
|
|
+ we used a <literal>DelegatingFilterProxy</literal> with the name <quote>springSecurityFilterChain</quote>. You should now be able to
|
|
|
+ see that this is the name of the <classname>FilterChainProxy</classname> which is created by the namespace.
|
|
|
+ </para>
|
|
|
+ <section>
|
|
|
+ <title>Bypassing the Filter Chain</title>
|
|
|
+ <para>
|
|
|
+ As with the namespace, you can use the attribute <literal>filters = "none"</literal> as an alternative to supplying a filter bean list.
|
|
|
+ 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>
|
|
|
+ </section>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <section>
|
|
|
+ <title>Filter Ordering</title>
|
|
|
+ <para>The order that filters are defined in the chain
|
|
|
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>
|
|
|
+ using, the order should be as follows:
|
|
|
|
|
|
<orderedlist inheritnum="ignore" continuation="restarts">
|
|
|
<listitem>
|
|
|
- <para><literal>ChannelProcessingFilter</literal>, because it might
|
|
|
+ <para><classname>ChannelProcessingFilter</classname>, because it might
|
|
|
need to redirect to a different protocol</para>
|
|
|
</listitem>
|
|
|
|
|
|
<listitem>
|
|
|
- <para><literal>ConcurrentSessionFilter</literal>, because it
|
|
|
+ <para><classname>ConcurrentSessionFilter</classname>, because it
|
|
|
doesn't use any <classname>SecurityContextHolder</classname>
|
|
|
functionality but needs to update the
|
|
|
<interfacename>SessionRegistry</interfacename> to reflect ongoing requests
|
|
@@ -236,7 +150,7 @@
|
|
|
</listitem>
|
|
|
|
|
|
<listitem>
|
|
|
- <para><classname>HttpSessionContextIntegrationFilter</classname>, so a
|
|
|
+ <para><classname>SecurityContextPersistenceFilter</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>
|
|
@@ -246,10 +160,9 @@
|
|
|
|
|
|
<listitem>
|
|
|
<para>Authentication processing mechanisms -
|
|
|
- <literal>UsernamePasswordAuthenticationProcessingFilter</literal>,
|
|
|
- <literal>CasProcessingFilter</literal>,
|
|
|
- <literal>BasicProcessingFilter, HttpRequestIntegrationFilter,
|
|
|
- JbossIntegrationFilter</literal> etc - so that the
|
|
|
+ <classname>UsernamePasswordAuthenticationProcessingFilter</classname>,
|
|
|
+ <classname>CasProcessingFilter</classname>,
|
|
|
+ <classname>BasicProcessingFilter</classname> etc - so that the
|
|
|
<classname>SecurityContextHolder</classname> can be modified to
|
|
|
contain a valid <interfacename>Authentication</interfacename> request
|
|
|
token</para>
|
|
@@ -274,7 +187,7 @@
|
|
|
</listitem>
|
|
|
|
|
|
<listitem>
|
|
|
- <para><literal>AnonymousProcessingFilter</literal>, so that if no
|
|
|
+ <para><classname>AnonymousProcessingFilter</classname>, so that if no
|
|
|
earlier authentication processing mechanism updated the
|
|
|
<classname>SecurityContextHolder</classname>, an anonymous
|
|
|
<interfacename>Authentication</interfacename> object will be put there</para>
|
|
@@ -292,21 +205,20 @@
|
|
|
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>
|
|
|
+ </para>
|
|
|
</section>
|
|
|
+
|
|
|
+ <section>
|
|
|
+ <title>Use with other Filter-Based Frameworks</title>
|
|
|
+ <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>
|
|
|
<section xml:id="taglib">
|
|
|
<info><title>Tag Libraries</title></info>
|
|
|
|