|
@@ -2,13 +2,14 @@
|
|
|
xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
|
<title>Core Security Filters</title>
|
|
|
<para> There are some key filters which will always be used in a web application which uses
|
|
|
- Spring Security, so we'll look at these and their supporting classes and interfaces them
|
|
|
- first. We won't cover every feature, so be sure to look at the Javadoc for them if you want
|
|
|
- to get the complete picture.</para>
|
|
|
+ Spring Security, so we'll look at these and their supporting classes and interfaces first.
|
|
|
+ We won't cover every feature, so be sure to look at the Javadoc for them if you want to get
|
|
|
+ the complete picture.</para>
|
|
|
<section xml:id="filter-security-interceptor">
|
|
|
<title><classname>FilterSecurityInterceptor</classname></title>
|
|
|
<para>We've already seen <classname>FilterSecurityInterceptor</classname> briefly when
|
|
|
- discussing <link xlink:href="#tech-intro-access-control">access-control in general</link>, and we've already used it with the namespace where the
|
|
|
+ discussing <link xlink:href="#tech-intro-access-control">access-control in
|
|
|
+ general</link>, and we've already used it with the namespace where the
|
|
|
<literal><intercept-url></literal> elements are combined to configure it
|
|
|
internally. Now we'll see how to explicitly configure it for use with a
|
|
|
<classname>FilterChainProxy</classname>, along with its companion filter
|
|
@@ -30,7 +31,8 @@
|
|
|
<interfacename>AuthenticationManager</interfacename> and an
|
|
|
<interfacename>AccessDecisionManager</interfacename>. It is also supplied with
|
|
|
configuration attributes that apply to different HTTP URL requests. Refer back to <link
|
|
|
- xlink:href="#tech-intro-config-attributes">the original discussion on these</link> in the technical introduction.</para>
|
|
|
+ xlink:href="#tech-intro-config-attributes">the original discussion on these</link>
|
|
|
+ in the technical introduction.</para>
|
|
|
<para>The <classname>FilterSecurityInterceptor</classname> can be configured with
|
|
|
configuration attributes in two ways. The first, which is shown above, is using the
|
|
|
<literal><filter-security-metadata-source></literal> namespace element. This
|
|
@@ -155,159 +157,147 @@
|
|
|
<classname>AccessDeniedHandlerImpl</classname> is used, which just sends a 403
|
|
|
(Forbidden) response to the client. Alternatively you can configure an instance
|
|
|
explicitly (as in the above example) and set an error page URL which it will
|
|
|
- forwards the request to <footnote>
|
|
|
- <para>We use a forward so that the SecurityContextHolder still contains details
|
|
|
- of the principal, which may be useful for displaying to the user. In old
|
|
|
- releases of Spring Security we relied upon the servlet container to handle a
|
|
|
- 403 error message, which lacked this useful contextual information.</para>
|
|
|
- </footnote>. This can be a simple <quote>access denied</quote> page, such as a JSP,
|
|
|
- or it could be a more complex handler such as an MVC controller. And of course, you
|
|
|
- can implement the interface yourself and use your own implementation. </para>
|
|
|
+ forwards the request to <footnote><para>We use a forward so that the
|
|
|
+ SecurityContextHolder still contains details of the principal, which may be
|
|
|
+ useful for displaying to the user. In old releases of Spring Security we
|
|
|
+ relied upon the servlet container to handle a 403 error message, which
|
|
|
+ lacked this useful contextual information.</para></footnote>. This can be a
|
|
|
+ simple <quote>access denied</quote> page, such as a JSP, or it could be a more
|
|
|
+ complex handler such as an MVC controller. And of course, you can implement the
|
|
|
+ interface yourself and use your own implementation. </para>
|
|
|
<para>It's also possible to supply a custom
|
|
|
<interfacename>AccessDeniedHandler</interfacename> when you're using the
|
|
|
- namespace to configure your application. See
|
|
|
- <link xlink:href="#nsa-access-denied-handler">the namespace appendix</link> for more details.</para>
|
|
|
+ namespace to configure your application. See <link
|
|
|
+ xlink:href="#nsa-access-denied-handler">the namespace appendix</link> for more
|
|
|
+ details.</para>
|
|
|
</section>
|
|
|
- <section xml:id="security-context-persistence-filter">
|
|
|
- <title><classname>SecurityContextPersistenceFilter</classname></title>
|
|
|
- <para> We covered the purpose of this all-important filter in <link
|
|
|
- xlink:href="#tech-intro-sec-context-persistence"/> so you might want to re-read
|
|
|
- that section at this point. Let's first take a look at how you would configure it
|
|
|
- for use with a <classname>FilterChainProxy</classname>. A basic configuration only
|
|
|
- requires the bean itself <programlisting><![CDATA[
|
|
|
+ </section>
|
|
|
+ <section xml:id="security-context-persistence-filter">
|
|
|
+ <title><classname>SecurityContextPersistenceFilter</classname></title>
|
|
|
+ <para> We covered the purpose of this all-important filter in <link
|
|
|
+ xlink:href="#tech-intro-sec-context-persistence"/> so you might want to re-read that
|
|
|
+ section at this point. Let's first take a look at how you would configure it for use
|
|
|
+ with a <classname>FilterChainProxy</classname>. A basic configuration only requires the
|
|
|
+ bean itself <programlisting><![CDATA[
|
|
|
<bean id="securityContextPersistenceFilter"
|
|
|
- class="org.springframework.security.web.context.SecurityContextPersistenceFilter"/>
|
|
|
- ]]></programlisting> As we saw previously, this filter has two main tasks. It is responsible for
|
|
|
- storage of the <classname>SecurityContext</classname> contents between HTTP requests
|
|
|
- and for clearing the <classname>SecurityContextHolder</classname> when a request is
|
|
|
- completed. Clearing the <classname>ThreadLocal</classname> in which the context is
|
|
|
- stored is essential, as it might otherwise be possible for a thread to be replaced
|
|
|
- into the servlet container's thread pool, with the security context for a particular
|
|
|
- user still attached. This thread might then be used at a later stage, performing
|
|
|
- operations with the wrong credentials. </para>
|
|
|
- <section xml:id="security-context-repository">
|
|
|
- <title><interfacename>SecurityContextRepository</interfacename></title>
|
|
|
- <para>From Spring Security 3.0, the job of loading and storing the security context
|
|
|
- is now delegated to a separate strategy interface:
|
|
|
- <programlisting language="java">
|
|
|
+class="org.springframework.security.web.context.SecurityContextPersistenceFilter"/>
|
|
|
+]]></programlisting> As we saw previously, this filter has two main tasks. It is responsible for
|
|
|
+ storage of the <classname>SecurityContext</classname> contents between HTTP requests and
|
|
|
+ for clearing the <classname>SecurityContextHolder</classname> when a request is
|
|
|
+ completed. Clearing the <classname>ThreadLocal</classname> in which the context is
|
|
|
+ stored is essential, as it might otherwise be possible for a thread to be replaced into
|
|
|
+ the servlet container's thread pool, with the security context for a particular user
|
|
|
+ still attached. This thread might then be used at a later stage, performing operations
|
|
|
+ with the wrong credentials. </para>
|
|
|
+ <section xml:id="security-context-repository">
|
|
|
+ <title><interfacename>SecurityContextRepository</interfacename></title>
|
|
|
+ <para>From Spring Security 3.0, the job of loading and storing the security context is
|
|
|
+ now delegated to a separate strategy interface:
|
|
|
+ <programlisting language="java">
|
|
|
public interface SecurityContextRepository {
|
|
|
- SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder);
|
|
|
- void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response);
|
|
|
+SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder);
|
|
|
+void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response);
|
|
|
}
|
|
|
</programlisting>
|
|
|
- The <classname>HttpRequestResponseHolder</classname> is simply a container for
|
|
|
- the incoming request and response objects, allowing the implementation to
|
|
|
- replace these with wrapper classes. The returned contents will be passed to the
|
|
|
- filter chain. </para>
|
|
|
- <para> The default implementation is
|
|
|
- <classname>HttpSessionSecurityContextRepository</classname>, which stores
|
|
|
- the security context as an <interfacename>HttpSession</interfacename> attribute <footnote>
|
|
|
- <para>In Spring Security 2.0 and earlier, this filter was called
|
|
|
- <classname>HttpSessionContextIntegrationFilter</classname> and
|
|
|
- performed all the work of storing the context was performed by the
|
|
|
- filter itself. If you were familiar with this class, then most of the
|
|
|
- configuration options which were available can now be found on
|
|
|
- <classname>HttpSessionSecurityContextRepository</classname>. </para>
|
|
|
- </footnote>. The most important configuration parameter for this implementation
|
|
|
- is the <literal>allowSessionCreation</literal> property, which defaults to
|
|
|
- <literal>true</literal>, thus allowing the class to create a session if it
|
|
|
- needs one to store the security context for an authenticated user (it won't
|
|
|
- create one unless authentication has taken place and the contents of the
|
|
|
- security context have changed). If you don't want a session to be created, then
|
|
|
- you can set this property to <literal>false</literal>: <programlisting language="xml"><![CDATA[
|
|
|
+ The <classname>HttpRequestResponseHolder</classname> is simply a container for the
|
|
|
+ incoming request and response objects, allowing the implementation to replace these
|
|
|
+ with wrapper classes. The returned contents will be passed to the filter chain. </para>
|
|
|
+ <para> The default implementation is
|
|
|
+ <classname>HttpSessionSecurityContextRepository</classname>, which stores the
|
|
|
+ security context as an <interfacename>HttpSession</interfacename> attribute
|
|
|
+ <footnote><para>In Spring Security 2.0 and earlier, this filter was called
|
|
|
+ <classname>HttpSessionContextIntegrationFilter</classname> and performed
|
|
|
+ all the work of storing the context was performed by the filter itself. If
|
|
|
+ you were familiar with this class, then most of the configuration options
|
|
|
+ which were available can now be found on
|
|
|
+ <classname>HttpSessionSecurityContextRepository</classname>.
|
|
|
+ </para></footnote>. The most important configuration parameter for this
|
|
|
+ implementation is the <literal>allowSessionCreation</literal> property, which
|
|
|
+ defaults to <literal>true</literal>, thus allowing the class to create a session if
|
|
|
+ it needs one to store the security context for an authenticated user (it won't
|
|
|
+ create one unless authentication has taken place and the contents of the security
|
|
|
+ context have changed). If you don't want a session to be created, then you can set
|
|
|
+ this property to <literal>false</literal>: <programlisting language="xml"><![CDATA[
|
|
|
<bean id="securityContextPersistenceFilter"
|
|
|
- class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
|
|
|
- <property name='securityContextRepository'>
|
|
|
- <bean class='org.springframework.security.web.context.HttpSessionSecurityContextRepository'>
|
|
|
- <property name='allowSessionCreation' value='false' />
|
|
|
- </bean>
|
|
|
- </property>
|
|
|
+class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
|
|
|
+<property name='securityContextRepository'>
|
|
|
+<bean class='org.springframework.security.web.context.HttpSessionSecurityContextRepository'>
|
|
|
+ <property name='allowSessionCreation' value='false' />
|
|
|
</bean>
|
|
|
- ]]></programlisting> Alternatively you could provide a null implementation of the
|
|
|
- <interfacename>SecurityContextRepository</interfacename> interface. </para>
|
|
|
- </section>
|
|
|
+</property>
|
|
|
+</bean>
|
|
|
+]]></programlisting> Alternatively you could provide a null implementation of the
|
|
|
+ <interfacename>SecurityContextRepository</interfacename> interface. </para>
|
|
|
</section>
|
|
|
- <section xml:id="form-login-filter">
|
|
|
- <title><classname>UsernamePasswordAuthenticationProcessingFilter</classname></title>
|
|
|
- <para>We've now seen the three main filters which are always present in a Spring
|
|
|
- Security web configuration. These are also the three which are automatically created
|
|
|
- by the namespace <literal><http></literal> element and cannot be substituted
|
|
|
- with alternatives. The only thing that's missing now is an actual authentication
|
|
|
- mechanism, something that will allow a user to authenticate. This filter is the most
|
|
|
- commonly used authentication filter and the one that is most often customized <footnote>
|
|
|
- <para>For historical reasons, prior to Spring Security 3.0, this filter was
|
|
|
- called <classname>AuthenticationProcessingFilter</classname> and the entry
|
|
|
- point was called
|
|
|
- <classname>AuthenticationProcessingFilterEntryPoint</classname>. Since
|
|
|
- the framework now supports many different forms of authentication, they have
|
|
|
- both been given more specific names in 3.0.</para>
|
|
|
- </footnote>. It also provides the implementation used by the <form-login>
|
|
|
- element from the namespace. There are three stages required to configure it. <orderedlist>
|
|
|
- <listitem>
|
|
|
- <para>Configure a <classname>LoginUrlAuthenticationEntryPoint</classname>
|
|
|
- with the URL of the login page, just as we did above, and set it on the
|
|
|
- <classname>ExceptionTranslationFilter</classname>. </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>Implement the login page (using a JSP or MVC controller).</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>Configure an instance of
|
|
|
- <classname>UsernamePasswordAuthenticationProcessingFilter</classname>
|
|
|
- in the application context</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>Add the filter bean to your filter chain proxy (making sure you pay
|
|
|
- attention to the order). <!-- TODO: link --></para>
|
|
|
- </listitem>
|
|
|
- </orderedlist> The login form simply contains <literal>j_username</literal> and
|
|
|
- <literal>j_password</literal> input fields, and posts to the URL that is
|
|
|
- monitored by the filter (by default this is
|
|
|
- <literal>/j_spring_security_check</literal>). The basic filter configuration
|
|
|
- looks something like this: <programlisting><![CDATA[
|
|
|
+ </section>
|
|
|
+ <section xml:id="form-login-filter">
|
|
|
+ <title><classname>UsernamePasswordAuthenticationProcessingFilter</classname></title>
|
|
|
+ <para>We've now seen the three main filters which are always present in a Spring Security
|
|
|
+ web configuration. These are also the three which are automatically created by the
|
|
|
+ namespace <literal><http></literal> element and cannot be substituted with
|
|
|
+ alternatives. The only thing that's missing now is an actual authentication mechanism,
|
|
|
+ something that will allow a user to authenticate. This filter is the most commonly used
|
|
|
+ authentication filter and the one that is most often customized <footnote><para>For
|
|
|
+ historical reasons, prior to Spring Security 3.0, this filter was called
|
|
|
+ <classname>AuthenticationProcessingFilter</classname> and the entry point
|
|
|
+ was called <classname>AuthenticationProcessingFilterEntryPoint</classname>.
|
|
|
+ Since the framework now supports many different forms of authentication, they
|
|
|
+ have both been given more specific names in 3.0.</para></footnote>. It also
|
|
|
+ provides the implementation used by the <form-login> element from the namespace.
|
|
|
+ There are three stages required to configure it. <orderedlist><listitem><para>Configure
|
|
|
+ a <classname>LoginUrlAuthenticationEntryPoint</classname> with the URL of
|
|
|
+ the login page, just as we did above, and set it on the
|
|
|
+ <classname>ExceptionTranslationFilter</classname>.
|
|
|
+ </para></listitem><listitem><para>Implement the login page (using a JSP or
|
|
|
+ MVC controller).</para></listitem><listitem><para>Configure an instance of
|
|
|
+ <classname>UsernamePasswordAuthenticationProcessingFilter</classname> in
|
|
|
+ the application context</para></listitem><listitem><para>Add the filter bean
|
|
|
+ to your filter chain proxy (making sure you pay attention to the order).
|
|
|
+ <!-- TODO: link --></para></listitem></orderedlist> The login form simply
|
|
|
+ contains <literal>j_username</literal> and <literal>j_password</literal> input fields,
|
|
|
+ and posts to the URL that is monitored by the filter (by default this is
|
|
|
+ <literal>/j_spring_security_check</literal>). The basic filter configuration looks
|
|
|
+ something like this: <programlisting><![CDATA[
|
|
|
<bean id="authenticationProcessingFilter" class=
|
|
|
"org.springframework.security.web.authentication.UsernamePasswordAuthenticationProcessingFilter">
|
|
|
<property name="authenticationManager" ref="authenticationManager"/>
|
|
|
<property name="filterProcessesUrl" value="/j_spring_security_check"/>
|
|
|
</bean> ]]>
|
|
|
- </programlisting></para>
|
|
|
- <section xml:id="form-login-flow-handling">
|
|
|
- <title>Application Flow on Authentication Success and Failure</title>
|
|
|
- <para> The filter calls the configured
|
|
|
- <interfacename>AuthenticationManager</interfacename> to process each
|
|
|
- authentication request. The destination following a successful authentication or
|
|
|
- an authentication failure is controlled by the
|
|
|
- <interfacename>AuthenticationSuccessHandler</interfacename> and
|
|
|
- <interfacename>AuthenticationFailureHandler</interfacename> strategy
|
|
|
- interfaces, respectively. The filter has properties which allow you to set these
|
|
|
- so you can customize the behaviour completely <footnote>
|
|
|
- <para>In versions prior to 3.0, the application flow at this point had
|
|
|
- evolved to a stage was controlled by a mix of properties on this class
|
|
|
- and strategy plugins. The decision was made for 3.0 to refactor the code
|
|
|
- to make these two strategies entirely responsible. </para>
|
|
|
- </footnote>. Some standard implementations are supplied such as
|
|
|
- <classname>SimpleUrlAuthenticationSuccessHandler</classname>,
|
|
|
- <classname>SavedRequestAwareAuthenticationSuccessHandler</classname>,
|
|
|
- <classname>SimpleUrlAuthenticationFailureHandler</classname> and
|
|
|
- <classname>ExceptionMappingAuthenticationFailureHandler</classname>. Have a
|
|
|
- look at the Javadoc for these classes to see how they work. </para>
|
|
|
- <para>If authentication is successful, the resulting
|
|
|
- <interfacename>Authentication</interfacename> object will be placed into the
|
|
|
- <classname>SecurityContextHolder</classname>. The configured
|
|
|
- AuthenticationSuccessHandler will then be called to either redirect or forward
|
|
|
- the user to the approprate destination. By default a
|
|
|
- <classname>SavedRequestAwareAuthenticationSuccessHandler</classname> is
|
|
|
- used, which means that the user will be redirected to the original destination
|
|
|
- they requested before they were asked to login. <note>
|
|
|
- <para> The <classname>ExceptionTranslationFilter</classname> caches the
|
|
|
- original request a user makes. When the user authenticates, the request
|
|
|
- handler makes use of this cached request to obtain the original URL and
|
|
|
- redirect to it. The original request is then rebuilt and used as an
|
|
|
- alternative. </para>
|
|
|
- </note> If authentication fails, the configured
|
|
|
- <interfacename>AuthenticationFailureHandler</interfacename> will be invoked.
|
|
|
- </para>
|
|
|
- </section>
|
|
|
+ </programlisting></para>
|
|
|
+ <section xml:id="form-login-flow-handling">
|
|
|
+ <title>Application Flow on Authentication Success and Failure</title>
|
|
|
+ <para> The filter calls the configured
|
|
|
+ <interfacename>AuthenticationManager</interfacename> to process each
|
|
|
+ authentication request. The destination following a successful authentication or an
|
|
|
+ authentication failure is controlled by the
|
|
|
+ <interfacename>AuthenticationSuccessHandler</interfacename> and
|
|
|
+ <interfacename>AuthenticationFailureHandler</interfacename> strategy interfaces,
|
|
|
+ respectively. The filter has properties which allow you to set these so you can
|
|
|
+ customize the behaviour completely <footnote><para>In versions prior to 3.0, the
|
|
|
+ application flow at this point had evolved to a stage was controlled by a
|
|
|
+ mix of properties on this class and strategy plugins. The decision was made
|
|
|
+ for 3.0 to refactor the code to make these two strategies entirely
|
|
|
+ responsible. </para></footnote>. Some standard implementations are supplied
|
|
|
+ such as <classname>SimpleUrlAuthenticationSuccessHandler</classname>,
|
|
|
+ <classname>SavedRequestAwareAuthenticationSuccessHandler</classname>,
|
|
|
+ <classname>SimpleUrlAuthenticationFailureHandler</classname> and
|
|
|
+ <classname>ExceptionMappingAuthenticationFailureHandler</classname>. Have a look
|
|
|
+ at the Javadoc for these classes to see how they work. </para>
|
|
|
+ <para>If authentication is successful, the resulting
|
|
|
+ <interfacename>Authentication</interfacename> object will be placed into the
|
|
|
+ <classname>SecurityContextHolder</classname>. The configured
|
|
|
+ AuthenticationSuccessHandler will then be called to either redirect or forward the
|
|
|
+ user to the approprate destination. By default a
|
|
|
+ <classname>SavedRequestAwareAuthenticationSuccessHandler</classname> is used,
|
|
|
+ which means that the user will be redirected to the original destination they
|
|
|
+ requested before they were asked to login. <note><para> The
|
|
|
+ <classname>ExceptionTranslationFilter</classname> caches the original
|
|
|
+ request a user makes. When the user authenticates, the request handler makes
|
|
|
+ use of this cached request to obtain the original URL and redirect to it.
|
|
|
+ The original request is then rebuilt and used as an alternative.
|
|
|
+ </para></note> If authentication fails, the configured
|
|
|
+ <interfacename>AuthenticationFailureHandler</interfacename> will be invoked.
|
|
|
+ </para>
|
|
|
</section>
|
|
|
</section>
|
|
|
</chapter>
|