Fixed section boundaries in core-filters doc

This commit is contained in:
Luke Taylor 2009-09-15 15:58:05 +00:00
parent e7486fc203
commit 283aa1b34b
1 changed files with 133 additions and 143 deletions

View File

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