Manual updates

This commit is contained in:
Luke Taylor 2009-07-06 10:33:14 +00:00
parent 853b4c8753
commit be12d93f7a
7 changed files with 382 additions and 321 deletions

View File

@ -6,31 +6,49 @@
<info> <info>
<title>Overview</title> <title>Overview</title>
</info> </info>
<para>Particularly in the case of web request URI security, sometimes it is more convenient <para>It's generally considered good security practice to adopt a
to assign configuration attributes against every possible secure object invocation. Put <quote>deny-by-default</quote> where you explicitly specify what is allowed and
differently, sometimes it is nice to say <literal>ROLE_SOMETHING</literal> is required disallow everything else. Defining what is accessible to unauthenticated users is a
by default and only allow certain exceptions to this rule, such as for login, logout and similar situation, particularly for web applications. Many sites require that users must
home pages of an application. There are also other situations where anonymous be authenticated for anything other than a few URLs (for example the home and login
authentication would be desired, such as when an auditing interceptor queries the pages). In this case it is easiest to define access configuration attributes for these
<classname>SecurityContextHolder</classname> to identify which principal was specific URLs rather than have for every secured resource. Put differently, sometimes it
responsible for a given operation. Such classes can be authored with more robustness if is nice to say <literal>ROLE_SOMETHING</literal> is required by default and only allow
they know the <classname>SecurityContextHolder</classname> always contains an certain exceptions to this rule, such as for login, logout and home pages of an
<interfacename>Authentication</interfacename> object, and never application. You could also omit these pages from the filter chain entirely, thus
bypassing the access control checks, but this may be undesirable for other reasons,
particularly if the pages behave differently for authenticated users.</para>
<para>This is what we mean by anonymous authentication. Note that there is no real
conceptual difference between a user who is <quote>anonymously authenticated</quote> and
an unauthenticated user. Spring Security's anonymous authentication just gives you a
more convenient way to configure your access-control attributes. Calls to servlet API
calls such as <methodname>getCallerPrincipal</methodname>, for example, will still
return null even though there is actually an anonymous authentication object in the
<classname>SecurityContextHolder</classname>.</para>
<para>There are other situations where anonymous authentication is useful, such as when an
auditing interceptor queries the <classname>SecurityContextHolder</classname> to
identify which principal was responsible for a given operation. Classes can be authored
more robustly if they know the <classname>SecurityContextHolder</classname> always
contains an <interfacename>Authentication</interfacename> object, and never
<literal>null</literal>.</para> <literal>null</literal>.</para>
</section> </section>
<section xml:id="anonymous-config"> <section xml:id="anonymous-config">
<info> <info>
<title>Configuration</title> <title>Configuration</title>
</info> </info>
<para>Spring Security provides three classes that together provide an anonymous <para>Anonymous authentication support is provided automatically when using the HTTP
authentication feature. <literal>AnonymousAuthenticationToken</literal> is an configurain Spring Security 3.0 and can be customized (or disabled) using the
implementation of <interfacename>Authentication</interfacename>, and stores the <literal>&lt;anonymous></literal> element. You don't need to configure the beans
<interfacename>GrantedAuthority</interfacename>[]s which apply to the anonymous described here unless you are using traditional bean configuration.</para>
<para>Three classes that together provide the anonymous authentication feature.
<literal>AnonymousAuthenticationToken</literal> is an implementation of
<interfacename>Authentication</interfacename>, and stores the
<interfacename>GrantedAuthority</interfacename>s which apply to the anonymous
principal. There is a corresponding <literal>AnonymousAuthenticationProvider</literal>, principal. There is a corresponding <literal>AnonymousAuthenticationProvider</literal>,
which is chained into the <literal>ProviderManager</literal> so that which is chained into the <literal>ProviderManager</literal> so that
<literal>AnonymousAuthenticationTokens</literal> are accepted. Finally, there is an <literal>AnonymousAuthenticationToken</literal>s are accepted. Finally, there is an
AnonymousProcessingFilter, which is chained after the normal authentication mechanisms AnonymousProcessingFilter, which is chained after the normal authentication mechanisms
and automatically add an <literal>AnonymousAuthenticationToken</literal> to the and automatically adds an <literal>AnonymousAuthenticationToken</literal> to the
<classname>SecurityContextHolder</classname> if there is no existing <classname>SecurityContextHolder</classname> if there is no existing
<interfacename>Authentication</interfacename> held there. The definition of the <interfacename>Authentication</interfacename> held there. The definition of the
filter and authentication provider appears as follows:</para> filter and authentication provider appears as follows:</para>
@ -50,8 +68,22 @@
</programlisting> </programlisting>
</para> </para>
<para>The <literal>key</literal> is shared between the filter and authentication provider, <para>The <literal>key</literal> is shared between the filter and authentication provider,
so that tokens created by the former are accepted by the latter. The so that tokens created by the former are accepted by the latter<footnote>
<literal>userAttribute</literal> is expressed in the form of <para>The use of the <literal>key</literal> property should not be regarded as
providing any real security here. It is merely a book-keeping exercise. If you
are sharing a <classname>ProviderManager</classname> which contains an
<classname>AnonymousAuthenticationProvider</classname> in a scenario where
it is possible for an authenticating client to construct the
<interfacename>Authentication</interfacename> object (such as with RMI
invocations), then a malicious client could submit an
<classname>AnonyousAuthenticationToken</classname> which it had created
itself (with chosen username and authority list). If the <literal>key</literal>
is guessable or can be found out, then the token would be accepted by the
anonymous provider. This isn't a problem with normal usage but if you are using
RMI you would be best to use a customized <classname>ProviderManager</classname>
which omits the anonymous provider rather than sharing the one you use for your
HTTP authentication mechanisms.</para>
</footnote>. The <literal>userAttribute</literal> is expressed in the form of
<literal>usernameInTheAuthenticationToken,grantedAuthority[,grantedAuthority]</literal>. <literal>usernameInTheAuthenticationToken,grantedAuthority[,grantedAuthority]</literal>.
This is the same syntax as used after the equals sign for This is the same syntax as used after the equals sign for
<literal>InMemoryDaoImpl</literal>'s <literal>userMap</literal> property.</para> <literal>InMemoryDaoImpl</literal>'s <literal>userMap</literal> property.</para>
@ -59,7 +91,7 @@
can have security applied to them. For example:</para> can have security applied to them. For example:</para>
<para><programlisting> <para><programlisting>
<![CDATA[ <![CDATA[
<bean id="filterInvocationInterceptor" <bean id="filterSecurityInterceptor"
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor"> class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/> <property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/> <property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/>
@ -73,18 +105,31 @@
</security:filter-security-metadata-source>" + </security:filter-security-metadata-source>" +
</property> </property>
</bean>]]> </bean>]]>
</programlisting>Rounding out the anonymous authentication discussion is the </programlisting></para>
<literal>AuthenticationTrustResolver</literal> interface, with its corresponding </section>
<literal>AuthenticationTrustResolverImpl</literal> implementation. This interface <section xml:id="anonymous-auth-trust-resolver">
<title><interfacename>AuthenticationTrustResolver</interfacename></title>
<para>
Rounding out the anonymous authentication discussion is the
<interfacename>AuthenticationTrustResolver</interfacename> interface, with its corresponding
<literal>AuthenticationTrustResolverImpl</literal> implementation. This interface
provides an <literal>isAnonymous(Authentication)</literal> method, which allows provides an <literal>isAnonymous(Authentication)</literal> method, which allows
interested classes to take into account this special type of authentication status. The interested classes to take into account this special type of authentication status. The
<classname>ExceptionTranslationFilter</classname> uses this interface in processing <classname>ExceptionTranslationFilter</classname> uses this interface in processing
<literal>AccessDeniedException</literal>s. If an <literal>AccessDeniedException</literal>s. If an
<literal>AccessDeniedException</literal> is thrown, and the authentication is of an <literal>AccessDeniedException</literal> is thrown, and the authentication is of an
anonymous type, instead of throwing a 403 (forbidden) response, the filter will instead anonymous type, instead of throwing a 403 (forbidden) response, the filter will instead
commence the <interfacename>AuthenticationEntryPoint</interfacename> so the principal commence the <interfacename>AuthenticationEntryPoint</interfacename> so the principal
can authenticate properly. This is a necessary distinction, otherwise principals would can authenticate properly. This is a necessary distinction, otherwise principals would
always be deemed "authenticated" and never be given an opportunity to login via form, always be deemed <quote>authenticated</quote> and never be given an opportunity to login
basic, digest or some other normal authentication mechanism</para> via form, basic, digest or some other normal authentication mechanism.
</para>
<para>
You will often see the <literal>ROLE_ANONYMOUS</literal> attribute in the above interceptor configuration
replaced with <literal>IS_AUTHENTICATED_ANONYMOUSLY</literal>. This is an example of the use of the
<classname>AuthenticatedVoter</classname> which will see in ???. It uses an
<interfacename>AuthenticationTrustResolver</interfacename> to process this particular configuration
attribute and grant access to aonymous users.
</para>
</section> </section>
</chapter> </chapter>

View File

@ -86,7 +86,7 @@
<literal>/secure/</literal> pattern. If they were reversed, the <literal>/secure/</literal> pattern. If they were reversed, the
<literal>/secure/</literal> pattern would always match and the <literal>/secure/</literal> pattern would always match and the
<literal>/secure/super/</literal> pattern would never be evaluated.</para> <literal>/secure/super/</literal> pattern would never be evaluated.</para>
<!-- <!--
TODO: Put in FAQ instead. Or drop. TODO: Put in FAQ instead. Or drop.
<para>As with other security interceptors, the <literal>validateConfigAttributes</literal> <para>As with other security interceptors, the <literal>validateConfigAttributes</literal>
property is observed. When set to <literal>true</literal> (the default), at startup time property is observed. When set to <literal>true</literal> (the default), at startup time
@ -96,16 +96,15 @@
<interfacename>AccessDecisionManager</interfacename> or the <interfacename>AccessDecisionManager</interfacename> or the
<literal>RunAsManager</literal>. If neither of these can process a particular <literal>RunAsManager</literal>. If neither of these can process a particular
configuration attribute, an exception is thrown.</para> configuration attribute, an exception is thrown.</para>
--> -->
</section> </section>
<section xml:id="exception-translation-filter"> <section xml:id="exception-translation-filter">
<title> <title>
<classname>ExceptionTranslationFilter</classname></title> <classname>ExceptionTranslationFilter</classname></title>
<para>The <classname>ExceptionTranslationFilter</classname> sits above the <classname>FilterSecurityInterceptor</classname> <para>The <classname>ExceptionTranslationFilter</classname> sits above the
in the security filter stack. It doesn't do any actual security enforcement itself, <classname>FilterSecurityInterceptor</classname> in the security filter stack. It
but handles exceptions thrown by the security interceptors and provides suitable doesn't do any actual security enforcement itself, but handles exceptions thrown by the
and HTTP responses. security interceptors and provides suitable and HTTP responses. <programlisting language="xml"><![CDATA[
<programlisting language="xml"><![CDATA[
<bean id="exceptionTranslationFilter" <bean id="exceptionTranslationFilter"
class="org.springframework.security.web.access.ExceptionTranslationFilter"> class="org.springframework.security.web.access.ExceptionTranslationFilter">
<property name="authenticationEntryPoint" ref="authenticationEntryPoint"/> <property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
@ -121,22 +120,20 @@
class="org.springframework.security.web.access.AccessDeniedHandlerImpl"> class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<property name="errorPage" value="/accessDenied.htm"/> <property name="errorPage" value="/accessDenied.htm"/>
</bean> </bean>
]]></programlisting> ]]></programlisting></para>
</para>
<section xml:id="auth-entry-point"> <section xml:id="auth-entry-point">
<title><interfacename>AuthenticationEntryPoint</interfacename></title> <title><interfacename>AuthenticationEntryPoint</interfacename></title>
<para> <para> The <interfacename>AuthenticationEntryPoint</interfacename> will be called if the
The <interfacename>AuthenticationEntryPoint</interfacename> will be user requests a secure HTTP resource but they are not authenticated. An appropriate
called if the user requests a secure HTTP resource but they are not authenticated. An <exceptionname>AuthenticationException</exceptionname> or
appropriate <exceptionname>AuthenticationException</exceptionname> or <exceptionname>AccessDeniedException</exceptionname> will be thrown by a
<exceptionname>AccessDeniedException</exceptionname> will be thrown by a security security interceptor further down the call stack, triggering the
interceptor further down the call stack, triggering the <methodname>commence</methodname> method on the entry point. This does the job
<methodname>commence</methodname> method on the entry point. This does the job of of presenting the appropriate response to the user so that authentication can begin.
presenting the appropriate response to the user so that authentication can begin. The The one we've used here is <classname>LoginUrlAuthenticationEntryPoint</classname>,
one we've used here is <classname>LoginUrlAuthenticationEntryPoint</classname>, which which redirects the request to a different URL (typically a login page). The actual
redirects the request to a different URL (typically a login page). The actual implementation used will depend on the authentication mechanism you want to be used
implementation used will depend on the authentication mechanism you want to be used in in your application. </para>
your application. </para>
</section> </section>
<section xml:id="access-denied-handler"> <section xml:id="access-denied-handler">
<title><interfacename>AccessDeniedHandler</interfacename></title> <title><interfacename>AccessDeniedHandler</interfacename></title>
@ -156,65 +153,69 @@
for which they don't have enough permissions. In this case, for which they don't have enough permissions. In this case,
<classname>ExceptionTranslationFilter</classname> will invoke a second strategy, <classname>ExceptionTranslationFilter</classname> will invoke a second strategy,
the <interfacename>AccessDeniedHandler</interfacename>. By default, an the <interfacename>AccessDeniedHandler</interfacename>. By default, an
<classname>AccessDeniedHandlerImpl</classname> is used, which just sends a 403 (Forbidden) <classname>AccessDeniedHandlerImpl</classname> is used, which just sends a 403
response to the client. Alternatively you can configure an instance explicitly (as in (Forbidden) response to the client. Alternatively you can configure an instance
the above example) and set an error page URL which it will forwards the request to explicitly (as in the above example) and set an error page URL which it will
<footnote><para>We use a forward so that the SecurityContextHolder still contains details of the principal, forwards the request to <footnote>
which may be useful for displaying to the user. In old releases of Spring Security we relied upon the servlet <para>We use a forward so that the SecurityContextHolder still contains details
container to handle a 403 error message, which lacked this useful contextual information.</para></footnote>. of the principal, which may be useful for displaying to the user. In old
This can be a simple <quote>access denied</quote> page, such as a JSP, or it could be releases of Spring Security we relied upon the servlet container to handle a
a more complex handler such as an MVC controller. And of course, you can implement the 403 error message, which lacked this useful contextual information.</para>
interface yourself and use your own implementation. </footnote>. This can be a simple <quote>access denied</quote> page, such as a JSP,
</para> or it could be a more complex handler such as an MVC controller. And of course, you
<para>It's also possible to supply a custom <interfacename>AccessDeniedHandler</interfacename> when you're can implement the interface yourself and use your own implementation. </para>
using the namespace to configure your application. See <link xlink:href="#nsa-access-denied-handler"/>.</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"/>.</para>
</section> </section>
<section xml:id="security-context-persistence-filter"> <section xml:id="security-context-persistence-filter">
<title><classname>SecurityContextPersistenceFilter</classname></title> <title><classname>SecurityContextPersistenceFilter</classname></title>
<para> <para> We covered the purpose of this all-important filter in <link
We covered the purpose of this all-important filter in <link xlink:href="#tech-intro-sec-context-persistence"/> so xlink:href="#tech-intro-sec-context-persistence"/> so you might want to re-read
you might want to re-read that section at this point. Let's first take a look at how you would configure it 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 for use with a <classname>FilterChainProxy</classname>. A basic configuration only
<programlisting><![CDATA[ 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> ]]></programlisting> As we saw previously, this filter has two main tasks. It is responsible for
As we saw previously, this filter has two main tasks. It is responsible for storage of the <classname>SecurityContext</classname> storage of the <classname>SecurityContext</classname> contents between HTTP requests
contents between HTTP requests and for clearing the <classname>SecurityContextHolder</classname> when a request is completed. and for clearing the <classname>SecurityContextHolder</classname> when a request is
Clearing the <classname>ThreadLocal</classname> in which the context is stored is essential, as it might otherwise be possible for completed. Clearing the <classname>ThreadLocal</classname> in which the context is
a thread to be replaced into the servlet container's thread pool, with the security context for a particular user still stored is essential, as it might otherwise be possible for a thread to be replaced
attached. This thread might then be used at a later stage, performing operations with the wrong credentials. into the servlet container's thread pool, with the security context for a particular
</para> 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"> <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 is now delegated <para>From Spring Security 3.0, the job of loading and storing the security context
to a separate strategy interface: is 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 incoming request and The <classname>HttpRequestResponseHolder</classname> is simply a container for
response objects, allowing the implementation to replace these with wrapper classes. The the incoming request and response objects, allowing the implementation to
returned contents will be passed to the filter chain. replace these with wrapper classes. The returned contents will be passed to the
</para> filter chain. </para>
<para> <para> The default implementation is
The default implementation is <classname>HttpSessionSecurityContextRepository</classname>, which <classname>HttpSessionSecurityContextRepository</classname>, which stores
stores the 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 all the work of <classname>HttpSessionContextIntegrationFilter</classname> and
storing the context was performed by the filter itself. If you were familiar with this class, performed all the work of storing the context was performed by the
then most of the configuration options which were available can now be found on filter itself. If you were familiar with this class, then most of the
<classname>HttpSessionSecurityContextRepository</classname>. configuration options which were available can now be found on
</para></footnote>. <classname>HttpSessionSecurityContextRepository</classname>. </para>
The most important configuration parameter for this implementation is the </footnote>. The most important configuration parameter for this implementation
<literal>allowSessionCreation</literal> property, which defaults to <literal>true</literal>, thus is the <literal>allowSessionCreation</literal> property, which defaults to
allowing the class to create a session if it needs one to store the security context for an authenticated <literal>true</literal>, thus allowing the class to create a session if it
user (it won't create one unless authentication has taken place and the contents of the security context have changed). needs one to store the security context for an authenticated user (it won't
If you don't want a session to be created, then you can set this property to <literal>false</literal>: create one unless authentication has taken place and the contents of the
<programlisting language="xml"><![CDATA[ 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" <bean id="securityContextPersistenceFilter"
class="org.springframework.security.web.context.SecurityContextPersistenceFilter"> class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
<property name='securityContextRepository'> <property name='securityContextRepository'>
@ -223,83 +224,89 @@ public interface SecurityContextRepository {
</bean> </bean>
</property> </property>
</bean> </bean>
]]></programlisting> ]]></programlisting> Alternatively you could provide a null implementation of the
<interfacename>SecurityContextRepository</interfacename> interface. </para>
Alternatively you could provide a null implementation of the <interfacename>SecurityContextRepository</interfacename> interface.
</para>
</section> </section>
</section> </section>
<section xml:id="form-login-filter"> <section xml:id="form-login-filter">
<title><classname>UsernamePasswordAuthenticationProcessingFilter</classname></title> <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 <para>We've now seen the three main filters which are always present in a Spring
are also the three which are automatically created by the namespace <literal>&lt;http&gt;</literal> element and Security web configuration. These are also the three which are automatically created
cannot be substituted with alternatives. The only thing that's missing now is an actual authentication mechanism, something by the namespace <literal>&lt;http&gt;</literal> element and cannot be substituted
that will allow a user to authenticate. This filter is the most commonly used authentication filter and the one with alternatives. The only thing that's missing now is an actual authentication
that is most often customized mechanism, something that will allow a user to authenticate. This filter is the most
<footnote><para>For historical reasons, prior to Spring Security 3.0, this filter was called commonly used authentication filter and the one that is most often customized <footnote>
<classname>AuthenticationProcessingFilter</classname> and the entry point was called <para>For historical reasons, prior to Spring Security 3.0, this filter was
<classname>AuthenticationProcessingFilterEntryPoint</classname>. Since the framework now supports called <classname>AuthenticationProcessingFilter</classname> and the entry
many different forms of authentication, they have both been given more specific names in 3.0.</para></footnote>. point was called
It also provides the implementation used by the &lt;form-login&gt; element from the namespace. <classname>AuthenticationProcessingFilterEntryPoint</classname>. Since
There are three stages required to configure it. the framework now supports many different forms of authentication, they have
<orderedlist> both been given more specific names in 3.0.</para>
<listitem><para>Configure a <classname>LoginUrlAuthenticationEntryPoint</classname> with the URL </footnote>. It also provides the implementation used by the &lt;form-login&gt;
of the login page, just as we did above, and set it on the <classname>ExceptionTranslationFilter</classname>. element from the namespace. There are three stages required to configure it. <orderedlist>
</para> <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>
<listitem><para>Implement the login page (using a JSP or MVC controller).</para></listitem> <listitem>
<listitem><para>Configure an instance of <classname>UsernamePasswordAuthenticationProcessingFilter</classname> in the application context</para></listitem> <para>Implement the login page (using a JSP or MVC controller).</para>
<listitem><para>Add the filter bean to your filter chain proxy (making sure you pay attention to the order). <!-- TODO: link --></para></listitem> </listitem>
</orderedlist> <listitem>
The login form simply contains <literal>j_username</literal> and <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 <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>). monitored by the filter (by default this is
The basic filter configuration looks something like this: <literal>/j_spring_security_check</literal>). The basic filter configuration
<programlisting><![CDATA[ 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> </programlisting></para>
</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> <para> The filter calls the configured
The filter calls the configured <interfacename>AuthenticationManager</interfacename> <interfacename>AuthenticationManager</interfacename> to process each
processes each authentication request. The destination following a successful authentication authentication request. The destination following a successful authentication or
or an authentication failure is controlled by the <interfacename>AuthenticationSuccessHandler</interfacename> an authentication failure is controlled by the
and <interfacename>AuthenticationFailureHandler</interfacename> strategy interfaces, respectively. <interfacename>AuthenticationSuccessHandler</interfacename> and
The filter has properties which allow you to set these so you can customize the behaviour as <interfacename>AuthenticationFailureHandler</interfacename> strategy
much as you want interfaces, respectively. The filter has properties which allow you to set these
<footnote><para>In versions prior to 3.0, the application flow at this point had evolved to a stage so you can customize the behaviour completely <footnote>
was controlled by a mix of properties on this class and strategy plugins. The <para>In versions prior to 3.0, the application flow at this point had
decision was made for 3.0 to refactor the code to make these two strategies entirely responsible. evolved to a stage was controlled by a mix of properties on this class
</para></footnote>. and strategy plugins. The decision was made for 3.0 to refactor the code
Some standard implementations are supplied such as to make these two strategies entirely responsible. </para>
<classname>SimpleUrlAuthenticationSuccessHandler</classname>, </footnote>. Some standard implementations are supplied such as
<classname>SavedRequestAwareAuthenticationSuccessHandler</classname>, <classname>SimpleUrlAuthenticationSuccessHandler</classname>,
<classname>SimpleUrlAuthenticationFailureHandler</classname> and <classname>SavedRequestAwareAuthenticationSuccessHandler</classname>,
<classname>ExceptionMappingAuthenticationFailureHandler</classname>. Have a look at the Javadoc <classname>SimpleUrlAuthenticationFailureHandler</classname> and
for these classes to see how they work. <classname>ExceptionMappingAuthenticationFailureHandler</classname>. Have a
</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>. <classname>SecurityContextHolder</classname>. The configured
The configured AuthenticationSuccessHandler will then be called to either redirect or forward AuthenticationSuccessHandler will then be called to either redirect or forward
the user to the approprate destination. By default a <classname>SavedRequestAwareAuthenticationSuccessHandler</classname> the user to the approprate destination. By default a
is used, which means that the user will be redirected to the original destination they requested before they were asked to <classname>SavedRequestAwareAuthenticationSuccessHandler</classname> is
login. used, which means that the user will be redirected to the original destination
<note> they requested before they were asked to login. <note>
<para> <para> The <classname>ExceptionTranslationFilter</classname> caches the
The <classname>ExceptionTranslationFilter</classname> caches the original request a user makes. original request a user makes. When the user authenticates, the request
When the user authenticates, the request handler makes use of this cached request to obtain the original handler makes use of this cached request to obtain the original URL and
URL and redirect to it. 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> alternative. </para>
</note> </note> If authentication fails, the configured
If authentication fails, the configured <interfacename>AuthenticationFailureHandler</interfacename> will be invoked. <interfacename>AuthenticationFailureHandler</interfacename> will be invoked.
</para> </para>
</section> </section>
</section> </section>

View File

@ -27,17 +27,15 @@
chapter and refresh your memory. The most common approach to verifying an authentication chapter and refresh your memory. The most common approach to verifying an authentication
request is to load the corresponding <interfacename>UserDetails</interfacename> and request is to load the corresponding <interfacename>UserDetails</interfacename> and
check the loaded password against the one that has been entered by the user. This is the check the loaded password against the one that has been entered by the user. This is the
approach used by the <classname>DaoAuthenticationProvider</classname>, which wraps a approach used by the <classname>DaoAuthenticationProvider</classname> (see below). The
<interfacename>UserDetailsService</interfacename> to implement an loaded <interfacename>UserDetails</interfacename> object - and particularly the
<interfacename>AuthenticationProvider</interfacename>. The loaded
<interfacename>UserDetails</interfacename> object - and particularly the
<literal>GrantedAuthority</literal>s it contains - will be used when building the <literal>GrantedAuthority</literal>s it contains - will be used when building the
fully populated <interfacename>Authentication</interfacename> object which is returned fully populated <interfacename>Authentication</interfacename> object which is returned
from a successful authentication and stored in the from a successful authentication and stored in the
<classname>SecurityContext</classname>. </para> <classname>SecurityContext</classname>. </para>
<para> If you are using the namespace, an instance of <para> If you are using the namespace, an instance of
<classname>ProviderMananger</classname> is created and maintained internally, and <classname>ProviderMananger</classname> is created and maintained internally, and
you add providers to it either by using the namespace authentication provired elements, you add providers to it either by using the namespace authentication provider elements,
or by adding the <literal>&lt;custom-authentication-provider&gt;</literal> element to a or by adding the <literal>&lt;custom-authentication-provider&gt;</literal> element to a
bean (see <link xlink:href="#ns-auth-manager">the namespace chapter</link>). In this bean (see <link xlink:href="#ns-auth-manager">the namespace chapter</link>). In this
case, you should not declare a <classname>ProviderManager</classname> bean in your case, you should not declare a <classname>ProviderManager</classname> bean in your
@ -76,6 +74,33 @@
concerned about this, because if you forget to register a suitable provider, you'll concerned about this, because if you forget to register a suitable provider, you'll
simply receive a <literal>ProviderNotFoundException</literal> when an attempt to simply receive a <literal>ProviderNotFoundException</literal> when an attempt to
authenticate is made.</para> authenticate is made.</para>
<section>
<title><literal>DaoAuthenticationProvider</literal></title>
<para>The simplest <interfacename>AuthenticationProvider</interfacename> implemented by
Spring Security is <literal>DaoAuthenticationProvider</literal>, which is is also
one of the earliest supported by the framework. It leverages a
<interfacename>UserDetailsService</interfacename> (as a DAO) in order to lookup
the username, password and <interfacename>GrantedAuthority</interfacename>s. It
authenticates the user simply by comparing the password submitted in a
<classname>UsernamePasswordAuthenticationToken</classname> against the one
loaded by the <interfacename>UserDetailsService</interfacename>. Configuring the
provider is quite simple:
<programlisting language="xml"><![CDATA[
<bean id="daoAuthenticationProvider"
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="inMemoryDaoImpl"/>
<property name="saltSource" ref bean="saltSource"/>
<property name="passwordEncoder" ref="passwordEncoder"/>
</bean>]]></programlisting>
The <interfacename>PasswordEncoder</interfacename> and <interfacename>SaltSource</interfacename> are
optional. A <interfacename>PasswordEncoder</interfacename> provides encoding and decoding of passwords
presented in the <interfacename>UserDetails</interfacename> object that is returned from the configured
<interfacename>UserDetailsService</interfacename>. A <interfacename>SaltSource</interfacename> enables
the passwords to be populated with a "salt", which enhances the security of the
passwords in the authentication repository. These will be discussed in more detail in ???.
<!-- TODO: Add sections on password encoding and user caching to advaced topics -->
</para>
</section>
</section> </section>
<section> <section>
<title><interfacename>UserDetailsService</interfacename> Implementations</title> <title><interfacename>UserDetailsService</interfacename> Implementations</title>

View File

@ -1,36 +1,34 @@
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="dao-provider"> <chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="dao-provider">
<info>
<info><title>DAO Authentication Provider</title></info> <title>DAO Authentication Provider</title>
</info>
<section xml:id="dao-provider-overview"> <section xml:id="dao-provider-overview">
<info><title>Overview</title></info> <info>
<title>Overview</title>
<para>Spring Security includes a production-quality </info>
<classname>AuthenticationProvider</classname> implementation called <para>Spring Security includes a production-quality
<literal>DaoAuthenticationProvider</literal>. This authentication <classname>AuthenticationProvider</classname> implementation called
provider is compatible with all of the authentication mechanisms that <literal>DaoAuthenticationProvider</literal>. This authentication provider is
generate a <literal>UsernamePasswordAuthenticationToken</literal>, and compatible with all of the authentication mechanisms that generate a
is probably the most commonly used provider in the framework. Like <literal>UsernamePasswordAuthenticationToken</literal>, and is probably the most
most of the other authentication providers, the commonly used provider in the framework. Like most of the other authentication
DaoAuthenticationProvider leverages a UserDetailsService in order to providers, the DaoAuthenticationProvider leverages a UserDetailsService in order to
lookup the username, password and GrantedAuthority[]s. Unlike most of lookup the username, password and GrantedAuthority[]s. Unlike most of the other
the other authentication providers that leverage UserDetailsService, authentication providers that leverage UserDetailsService, this authentication provider
this authentication provider actually requires the password to be actually requires the password to be presented, and the provider will actually evaluate
presented, and the provider will actually evaluate the validity or the validity or otherwise of the password presented in an authentication request
otherwise of the password presented in an authentication request object.</para>
object.</para> </section>
</section> <section xml:id="dao-provider-config">
<info>
<section xml:id="dao-provider-config"> <title>Configuration</title>
<info><title>Configuration</title></info> </info>
<para>Aside from adding DaoAuthenticationProvider to your ProviderManager list (as discussed
<para>Aside from adding DaoAuthenticationProvider to your at the start of this part of the reference guide), and ensuring a suitable
ProviderManager list (as discussed at the start of this part of the authentication mechanism is configured to present a UsernamePasswordAuthenticationToken,
reference guide), and ensuring a suitable authentication mechanism is the configuration of the provider itself is rather simple:</para>
configured to present a UsernamePasswordAuthenticationToken, the <para>
configuration of the provider itself is rather simple:</para> <programlisting>
<para><programlisting>
<![CDATA[ <![CDATA[
<bean id="daoAuthenticationProvider" <bean id="daoAuthenticationProvider"
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider"> class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
@ -38,38 +36,33 @@
<property name="saltSource" ref bean="saltSource"/> <property name="saltSource" ref bean="saltSource"/>
<property name="passwordEncoder" ref="passwordEncoder"/> <property name="passwordEncoder" ref="passwordEncoder"/>
</bean> ]]> </bean> ]]>
</programlisting></para> </programlisting>
</para>
<para>The <literal>PasswordEncoder</literal> and <para>The <literal>PasswordEncoder</literal> and <literal>SaltSource</literal> are optional.
<literal>SaltSource</literal> are optional. A A <literal>PasswordEncoder</literal> provides encoding and decoding of passwords
<literal>PasswordEncoder</literal> provides encoding and decoding of presented in the <interfacename>UserDetails</interfacename> object that is returned from
passwords presented in the <interfacename>UserDetails</interfacename> object that the configured <interfacename>UserDetailsService</interfacename>. A
is returned from the configured <interfacename>UserDetailsService</interfacename>. <literal>SaltSource</literal> enables the passwords to be populated with a "salt",
A <literal>SaltSource</literal> enables the passwords to be populated which enhances the security of the passwords in the authentication repository.
with a "salt", which enhances the security of the passwords in the <literal>PasswordEncoder</literal> implementations are provided with Spring Security
authentication repository. <literal>PasswordEncoder</literal> covering MD5, SHA and cleartext encodings. Two <literal>SaltSource</literal>
implementations are provided with Spring Security covering MD5, SHA implementations are also provided: <literal>SystemWideSaltSource</literal> which encodes
and cleartext encodings. Two <literal>SaltSource</literal> all passwords with the same salt, and <literal>ReflectionSaltSource</literal>, which
implementations are also provided: inspects a given property of the returned <interfacename>UserDetails</interfacename>
<literal>SystemWideSaltSource</literal> which encodes all passwords object to obtain the salt. Please refer to the JavaDocs for further details on these
with the same salt, and <literal>ReflectionSaltSource</literal>, which optional features.</para>
inspects a given property of the returned <para>In addition to the properties above, the <literal>DaoAuthenticationProvider</literal>
<interfacename>UserDetails</interfacename> object to obtain the salt. Please refer supports optional caching of <interfacename>UserDetails</interfacename> objects. The
to the JavaDocs for further details on these optional features.</para> <literal>UserCache</literal> interface enables the
<literal>DaoAuthenticationProvider</literal> to place a
<para>In addition to the properties above, the <interfacename>UserDetails</interfacename> object into the cache, and retrieve it
<literal>DaoAuthenticationProvider</literal> supports optional caching from the cache upon subsequent authentication attempts for the same username. By default
of <interfacename>UserDetails</interfacename> objects. The the <literal>DaoAuthenticationProvider</literal> uses the
<literal>UserCache</literal> interface enables the <literal>NullUserCache</literal>, which performs no caching. A usable caching
<literal>DaoAuthenticationProvider</literal> to place a implementation is also provided, <literal>EhCacheBasedUserCache</literal>, which is
<interfacename>UserDetails</interfacename> object into the cache, and retrieve it configured as follows:</para>
from the cache upon subsequent authentication attempts for the same <para>
username. By default the <literal>DaoAuthenticationProvider</literal> <programlisting><![CDATA[
uses the <literal>NullUserCache</literal>, which performs no caching.
A usable caching implementation is also provided,
<literal>EhCacheBasedUserCache</literal>, which is configured as
follows:</para>
<para><programlisting><![CDATA[
<bean id="daoAuthenticationProvider" <bean id="daoAuthenticationProvider"
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider"> class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="userDetailsService"/> <property name="userDetailsService" ref="userDetailsService"/>
@ -89,42 +82,19 @@
class="org.springframework.security.core.userdetails.cache.EhCacheBasedUserCache"> class="org.springframework.security.core.userdetails.cache.EhCacheBasedUserCache">
<property name="cache" ref="userCacheBackend"/> <property name="cache" ref="userCacheBackend"/>
</bean>]]> </bean>]]>
</programlisting></para> </programlisting>
</para>
<para>All Spring Security EH-CACHE implementations (including <para>All Spring Security EH-CACHE implementations (including
<literal>EhCacheBasedUserCache</literal>) require an EH-CACHE <literal>EhCacheBasedUserCache</literal>) require an EH-CACHE
<literal>Cache</literal> object. The <literal>Cache</literal> object <literal>Cache</literal> object. The <literal>Cache</literal> object can be obtained
can be obtained from wherever you like, although we recommend you use from wherever you like, although we recommend you use Spring's factory classes as shown
Spring's factory classes as shown in the above configuration. If using in the above configuration. If using Spring's factory classes, please refer to the
Spring's factory classes, please refer to the Spring documentation for Spring documentation for further details on how to optimise the cache storage location,
further details on how to optimise the cache storage location, memory memory usage, eviction policies, timeouts etc.</para>
usage, eviction policies, timeouts etc.</para> <note>
<note><para>In the majority of cases, where your application is a stateful web <para>In the majority of cases, where your application is a stateful web application,
application, you don't need to use a cache as the user's authentication you don't need to use a cache as the user's authentication information will be
information will be stored in the <literal>HttpSession</literal>. stored in the <literal>HttpSession</literal>. </para>
</para></note> </note>
</section>
<para>A design decision was made not to support account locking in the </chapter>
<literal>DaoAuthenticationProvider</literal>, as doing so would have
increased the complexity of the <interfacename>UserDetailsService</interfacename>
interface. For instance, a method would be required to increase the
count of unsuccessful authentication attempts. Such functionality
could be easily provided by leveraging the application event
publishing features discussed below.</para>
<para><literal>DaoAuthenticationProvider</literal> returns an
<interfacename>Authentication</interfacename> object which in turn has its
<literal>principal</literal> property set. The principal will be
either a <literal>String</literal> (which is essentially the username)
or a <interfacename>UserDetails</interfacename> object (which was looked up from
the <interfacename>UserDetailsService</interfacename>). By default the
<interfacename>UserDetails</interfacename> is returned, as this enables
applications to add extra properties potentially of use in
applications, such as the user's full name, email address etc. If
using container adapters, or if your applications were written to
operate with <literal>String</literal>s (as was the case for releases
prior to Spring Security 0.6), you should set the
<literal>DaoAuthenticationProvider.forcePrincipalAsString</literal>
property to <literal>true</literal> in your application context</para>
</section>
</chapter>

View File

@ -113,7 +113,7 @@
<section xml:id="ns-web-xml"> <section xml:id="ns-web-xml">
<title><literal>web.xml</literal> Configuration</title> <title><literal>web.xml</literal> Configuration</title>
<para> The first thing you need to do is add the following filter declaration to your <para> The first thing you need to do is add the following filter declaration to your
<literal>web.xml</literal> file: <programlisting language="xml"><![CDATA[ <literal>web.xml</literal> file: <programlisting language="xml"><![CDATA[
<filter> <filter>
<filter-name>springSecurityFilterChain</filter-name> <filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
@ -277,7 +277,7 @@
containing the standard Spring Security <link xlink:href="#db_schema_users_authorities">user containing the standard Spring Security <link xlink:href="#db_schema_users_authorities">user
data tables</link>. Alternatively, you could configure a Spring Security data tables</link>. Alternatively, you could configure a Spring Security
<classname>JdbcDaoImpl</classname> bean and point at that using the <classname>JdbcDaoImpl</classname> bean and point at that using the
<literal>user-service-ref</literal> attribute: <programlisting language="xml"><![CDATA[ <literal>user-service-ref</literal> attribute: <programlisting language="xml"><![CDATA[
<authentication-provider user-service-ref='myUserDetailsService'/> <authentication-provider user-service-ref='myUserDetailsService'/>
<beans:bean id="myUserDetailsService" <beans:bean id="myUserDetailsService"
@ -332,7 +332,7 @@
<title>Adding HTTP/HTTPS Channel Security</title> <title>Adding HTTP/HTTPS Channel Security</title>
<para>If your application supports both HTTP and HTTPS, and you require that particular URLs <para>If your application supports both HTTP and HTTPS, and you require that particular URLs
can only be accessed over HTTPS, then this is directly supported using the can only be accessed over HTTPS, then this is directly supported using the
<literal>requires-channel</literal> attribute on <literal>&lt;intercept-url&gt;</literal>: <programlisting language="xml"><![CDATA[ <literal>requires-channel</literal> attribute on <literal>&lt;intercept-url&gt;</literal>: <programlisting language="xml"><![CDATA[
<http> <http>
<intercept-url pattern="/secure/**" access="ROLE_USER" requires-channel="https"/> <intercept-url pattern="/secure/**" access="ROLE_USER" requires-channel="https"/>
<intercept-url pattern="/**" access="ROLE_USER" requires-channel="any"/> <intercept-url pattern="/**" access="ROLE_USER" requires-channel="any"/>
@ -406,14 +406,21 @@
version of a standard namespace filter, such as the version of a standard namespace filter, such as the
<literal>UsernamePasswordAuthenticationProcessingFilter</literal> which is created by the <literal>UsernamePasswordAuthenticationProcessingFilter</literal> which is created by the
<literal>&lt;form-login&gt;</literal> element, taking advantage of some of the extra <literal>&lt;form-login&gt;</literal> element, taking advantage of some of the extra
configuration options which are available by using defining the bean directly. How can you configuration options which are available by using the bean explicitly. How can you do this
do this with namespace configuration, since the filter chain is not directly exposed? </para> with namespace configuration, since the filter chain is not directly exposed? </para>
<para>The order of the filters is always strictly enforced when using the namespace. Each <para>The order of the filters is always strictly enforced when using the namespace. When the
Spring Security filter implements the Spring <interfacename>Ordered</interfacename> application context is being created, the filter beans are sorted by the namespace handling
interface and the filters created by the namespace are sorted during initialization. The code and the standard Spring Security filters each have an alias in the namespace and a
standard Spring Security filters each have an alias in the namespace. The filters, aliases well-known position.<note>
and namespace elements/attributes which create the filters are shown in <xref <para>In previous versions, the sorting took place after the filter instances had been
linkend="filter-stack"/>. <table xml:id="filter-stack"> created, during post-processing of the application context. In version 3.0+ the sorting
is now done at the bean metadata level, before the classes have been instantiated. This
has implications for how you add your own filters to the stack as the entire filter list
must be known during the parsing of the <literal>&lt;http></literal> element, so the
syntax has changed slightly in 3.0.</para>
</note>The filters, aliases and namespace elements/attributes which create the filters are
shown in <xref linkend="filter-stack"/>. The filters are listed in the order in which they
occur in the filter chain. <table xml:id="filter-stack">
<title>Standard Filter Aliases and Ordering</title> <title>Standard Filter Aliases and Ordering</title>
<tgroup cols="3" align="left"> <tgroup cols="3" align="left">
<thead> <thead>
@ -510,10 +517,13 @@
</table> You can add your own filter to the stack, using the </table> You can add your own filter to the stack, using the
<literal>custom-filter</literal> element and one of these names to specify the position <literal>custom-filter</literal> element and one of these names to specify the position
your filter should appear at: <programlisting language="xml"><![CDATA[ your filter should appear at: <programlisting language="xml"><![CDATA[
<beans:bean id="myFilter" class="com.mycompany.MySpecialAuthenticationFilter"> <http>
<custom-filter position="AUTHENTICATION_PROCESSING_FILTER"/> <custom-filter position="AUTHENTICATION_PROCESSING_FILTER" ref="myFilter" />
</beans:bean> </http>
]]></programlisting> You can also use the <literal>after</literal> or <literal>before</literal>
<beans:bean id="myFilter" class="com.mycompany.MySpecialAuthenticationFilter"/>
]]>
</programlisting> You can also use the <literal>after</literal> or <literal>before</literal>
attributes if you want your filter to be inserted before or after another filter in the attributes if you want your filter to be inserted before or after another filter in the
stack. The names "FIRST" and "LAST" can be used with the <literal>position</literal> stack. The names "FIRST" and "LAST" can be used with the <literal>position</literal>
attribute to indicate that you want your filter to appear before or after the entire stack, attribute to indicate that you want your filter to appear before or after the entire stack,
@ -575,12 +585,12 @@
</section> </section>
<section xml:id="ns-method-security"> <section xml:id="ns-method-security">
<title>Method Security</title> <title>Method Security</title>
<para>From version 2.0 onwards Spring Security has improved support substantially for adding security to your <para>From version 2.0 onwards Spring Security has improved support substantially for adding
service layer methods. It provides support for JSR-250 security security to your service layer methods. It provides support for JSR-250 security as well as
as well as the framework's native <literal>@Secured</literal> the framework's native <literal>@Secured</literal> annotation. You can apply security to a
annotation. You can apply security to a single bean, using the single bean, using the <literal>intercept-methods</literal> element to decorate the bean
<literal>intercept-methods</literal> element to decorate the bean declaration, or you can declaration, or you can secure multiple beans across the entire service layer using the
secure multiple beans across the entire service layer using the AspectJ style pointcuts. </para> AspectJ style pointcuts. </para>
<section xml:id="ns-global-method"> <section xml:id="ns-global-method">
<title>The <literal>&lt;global-method-security&gt;</literal> Element</title> <title>The <literal>&lt;global-method-security&gt;</literal> Element</title>
<para> This element is used to enable annotation-based security in your application (by <para> This element is used to enable annotation-based security in your application (by
@ -664,7 +674,7 @@
<para> For method security, you do this by setting the <para> For method security, you do this by setting the
<literal>access-decision-manager-ref</literal> attribute on <literal>access-decision-manager-ref</literal> attribute on
<literal>global-method-security</literal>to the Id of the appropriate <literal>global-method-security</literal>to the Id of the appropriate
<interfacename>AccessDecisionManager</interfacename> bean in the application context: <programlisting language="xml"><![CDATA[ <interfacename>AccessDecisionManager</interfacename> bean in the application context: <programlisting language="xml"><![CDATA[
<global-method-security access-decision-manager-ref="myAccessDecisionManagerBean"> <global-method-security access-decision-manager-ref="myAccessDecisionManagerBean">
... ...
</global-method-security> </global-method-security>
@ -681,8 +691,9 @@
<para> We've touched on the idea that the namespace configuration automatically registers an <para> We've touched on the idea that the namespace configuration automatically registers an
authentication manager bean for you. This is an instance of Spring Security's authentication manager bean for you. This is an instance of Spring Security's
<classname>ProviderManager</classname> class, which you may already be familiar with if <classname>ProviderManager</classname> class, which you may already be familiar with if
you've used the framework before. If not, it will be covered later, in <link xlink:href="#tech-intro-authentication"/>. you've used the framework before. If not, it will be covered later, in <link
You can't use a custom <classname>AuthenticationManager</classname> if you are using either HTTP or method security xlink:href="#tech-intro-authentication"/>. You can't use a custom
<classname>AuthenticationManager</classname> if you are using either HTTP or method security
through the namespace, but this should not be a problem as you have full control over the through the namespace, but this should not be a problem as you have full control over the
<classname>AuthenticationProvider</classname>s that are used. </para> <classname>AuthenticationProvider</classname>s that are used. </para>
<para> You may want to register additional <classname>AuthenticationProvider</classname> beans <para> You may want to register additional <classname>AuthenticationProvider</classname> beans

View File

@ -115,7 +115,9 @@
<xi:include href="basic-and-digest-auth.xml"/> <xi:include href="basic-and-digest-auth.xml"/>
<xi:include href="remember-me-authentication.xml"/> <xi:include href="remember-me-authentication.xml"/>
<xi:include href="concurrent-sessions.xml"/> <xi:include href="concurrent-sessions.xml"/>
<xi:include href="anon-auth-provider.xml"/>
</part> </part>
<!--
<part xml:id="authentication"> <part xml:id="authentication">
<title>Authentication</title> <title>Authentication</title>
<partintro> <partintro>
@ -138,9 +140,8 @@
</footnote>. </para> </footnote>. </para>
</partintro> </partintro>
<xi:include href="dao-auth-provider.xml"/> <xi:include href="dao-auth-provider.xml"/>
<xi:include href="anon-auth-provider.xml"/>
<xi:include href="runas-auth-provider.xml"/>
</part> </part>
-->
<part xml:id="authorization"> <part xml:id="authorization">
<title>Authorization</title> <title>Authorization</title>
<partintro> <partintro>
@ -164,7 +165,7 @@
Essentially standalone features which do not have to follow on directly from earlier chapters Essentially standalone features which do not have to follow on directly from earlier chapters
--> -->
<partintro> <partintro>
<para> In this part we cover some of the more advanced features of the framework. </para> <para> In this part we cover some of the more advanced and less-commonly used features of the framework.</para>
</partintro> </partintro>
<xi:include href="domain-acls.xml"/> <xi:include href="domain-acls.xml"/>
<xi:include href="preauth.xml"/> <xi:include href="preauth.xml"/>
@ -172,6 +173,7 @@
<xi:include href="jaas-auth-provider.xml"/> <xi:include href="jaas-auth-provider.xml"/>
<xi:include href="cas-auth-provider.xml"/> <xi:include href="cas-auth-provider.xml"/>
<xi:include href="x509-auth-provider.xml"/> <xi:include href="x509-auth-provider.xml"/>
<xi:include href="runas-auth-provider.xml"/>
</part> </part>
<xi:include href="appendix-db-schema.xml"/> <xi:include href="appendix-db-schema.xml"/>
<xi:include href="appendix-namespace.xml"/> <xi:include href="appendix-namespace.xml"/>

View File

@ -28,8 +28,8 @@
web-application security, LDAP or namespace configuration. We'll take a look here at some of web-application security, LDAP or namespace configuration. We'll take a look here at some of
the Java types that you'll find in the core module. They represent the building blocks of the the Java types that you'll find in the core module. They represent the building blocks of the
the framework, so if you ever need to go beyond a simple namespace configuration then it's the framework, so if you ever need to go beyond a simple namespace configuration then it's
important that you understand what they are, even if you don't actually need to directly important that you understand what they are, even if you don't actually need to interact with
interact with them.</para> them directly.</para>
<section> <section>
<title> SecurityContextHolder, SecurityContext and Authentication Objects </title> <title> SecurityContextHolder, SecurityContext and Authentication Objects </title>
<para>The most fundamental object is <classname>SecurityContextHolder</classname>. This is <para>The most fundamental object is <classname>SecurityContextHolder</classname>. This is
@ -44,13 +44,15 @@
no need to worry about it.</para> no need to worry about it.</para>
<para>Some applications aren't entirely suitable for using a <literal>ThreadLocal</literal>, <para>Some applications aren't entirely suitable for using a <literal>ThreadLocal</literal>,
because of the specific way they work with threads. For example, a Swing client might want because of the specific way they work with threads. For example, a Swing client might want
all threads in a Java Virtual Machine to use the same security context. For this situation all threads in a Java Virtual Machine to use the same security context.
you would use the <literal>SecurityContextHolder.MODE_GLOBAL</literal>. Other applications <classname>SecurityContextHolder</classname> can be configured with a strategy on startup
might want to have threads spawned by the secure thread also assume the same security to specify how you would like the contex to be stored. For a standalone application you
identity. This is achieved by using would use the <literal>SecurityContextHolder.MODE_GLOBAL</literal> strategy. Other
applications might want to have threads spawned by the secure thread also assume the same
security identity. This is achieved by using
<literal>SecurityContextHolder.MODE_INHERITABLETHREADLOCAL</literal>. You can change the <literal>SecurityContextHolder.MODE_INHERITABLETHREADLOCAL</literal>. You can change the
mode from the default <literal>SecurityContextHolder.MODE_THREADLOCAL</literal> in two ways. mode from the default <literal>SecurityContextHolder.MODE_THREADLOCAL</literal> in two ways.
The first is to set a system property. Alternatively, call a static method on The first is to set a system property, the second is to call a static method on
<classname>SecurityContextHolder</classname>. Most applications won't need to change from <classname>SecurityContextHolder</classname>. Most applications won't need to change from
the default, but if you do, take a look at the JavaDocs for the default, but if you do, take a look at the JavaDocs for
<classname>SecurityContextHolder</classname> to learn more.</para> <classname>SecurityContextHolder</classname> to learn more.</para>
@ -74,9 +76,9 @@ if (principal instanceof UserDetails) {
}</programlisting> }</programlisting>
<para>The object returned by the call to <methodname>getContext()</methodname> is an <para>The object returned by the call to <methodname>getContext()</methodname> is an
instance of the <interfacename>SecurityContext</interfacename> interface. This is the instance of the <interfacename>SecurityContext</interfacename> interface. This is the
object that is kept in thread-local storage. Most authentication mechanisms withing Spring object that is kept in thread-local storage. As we'll see below, Most authentication
Security return an instance of <interfacename>UserDetails</interfacename> as the principal mechanisms withing Spring Security return an instance of
as we'll see below. </para> <interfacename>UserDetails</interfacename> as the principal. </para>
</section> </section>
</section> </section>
<section> <section>
@ -109,15 +111,15 @@ if (principal instanceof UserDetails) {
<para> On successful authentication, <interfacename>UserDetails</interfacename> is used to <para> On successful authentication, <interfacename>UserDetails</interfacename> is used to
build the <interfacename>Authentication</interfacename> object that is stored in the build the <interfacename>Authentication</interfacename> object that is stored in the
<classname>SecurityContextHolder</classname> (more on this <link <classname>SecurityContextHolder</classname> (more on this <link
xlink:href="#tech-intro-authentication-mgr">below</link>). The good news is that we provide a xlink:href="#tech-intro-authentication-mgr">below</link>). The good news is that we
number of <interfacename>UserDetailsService</interfacename> implementations, including one provide a number of <interfacename>UserDetailsService</interfacename> implementations,
that uses an in-memory map (<classname>InMemoryDaoImpl</classname>) and another that uses including one that uses an in-memory map (<classname>InMemoryDaoImpl</classname>) and
JDBC (<interfacename>JdbcDaoImpl</interfacename>). Most users tend to write their own, another that uses JDBC (<interfacename>JdbcDaoImpl</interfacename>). Most users tend to
though, with their implementations often simply sitting on top of an existing Data Access write their own, though, with their implementations often simply sitting on top of an
Object (DAO) that represents their employees, customers, or other users of the application. existing Data Access Object (DAO) that represents their employees, customers, or other users
Remember the advantage that whatever your <interfacename>UserDetailsService</interfacename> of the application. Remember the advantage that whatever your
returns can always be obtained from the <classname>SecurityContextHolder</classname> using <interfacename>UserDetailsService</interfacename> returns can always be obtained from the
the above code fragment. </para> <classname>SecurityContextHolder</classname> using the above code fragment. </para>
</section> </section>
<section xml:id="tech-granted-authority"> <section xml:id="tech-granted-authority">
<title>GrantedAuthority</title> <title>GrantedAuthority</title>
@ -321,10 +323,8 @@ Successfully authenticated. Security context contains: \
(or equivalent) that reads the third-party user information from a location, build a (or equivalent) that reads the third-party user information from a location, build a
Spring Security-specific <interfacename>Authentication</interfacename> object, and put it Spring Security-specific <interfacename>Authentication</interfacename> object, and put it
onto the <classname>SecurityContextHolder</classname>.</para> onto the <classname>SecurityContextHolder</classname>.</para>
<para> <para> If you're wondering how the <interfacename>AuthenticationManager</interfacename>
If you're wondering how the <interfacename>AuthenticationManager</interfacename> manager is implemented in a real world example, we'll look at that in </para>
manager is implemented in a real world example, we'll look at that in
</para>
</section> </section>
</section> </section>
</section> </section>
@ -511,10 +511,11 @@ Successfully authenticated. Security context contains: \
<title>What are Configuration Attributes?</title> <title>What are Configuration Attributes?</title>
<para> A <quote>configuration attribute</quote> can be thought of as a String that has <para> A <quote>configuration attribute</quote> can be thought of as a String that has
special meaning to the classes used by <classname>AbstractSecurityInterceptor</classname>. special meaning to the classes used by <classname>AbstractSecurityInterceptor</classname>.
They are represented by the interface <interfacename>ConfigAttribute</interfacename> within They are represented by the interface <interfacename>ConfigAttribute</interfacename>
the framework. They may be simple role names or have more complex meaning, depending on the how within the framework. They may be simple role names or have more complex meaning,
sophisticated the <interfacename>AccessDecisionManager</interfacename> implementation is. depending on the how sophisticated the
The <classname>AbstractSecurityInterceptor</classname> is configured with a <interfacename>AccessDecisionManager</interfacename> implementation is. The
<classname>AbstractSecurityInterceptor</classname> is configured with a
<interfacename>SecurityMetadataSource</interfacename> which it uses to look up the <interfacename>SecurityMetadataSource</interfacename> which it uses to look up the
attributes for a secure object. Usually this configuration will be hidden from the user. attributes for a secure object. Usually this configuration will be hidden from the user.
Configuration attributes will be entered as annotations on secured methods, or as access Configuration attributes will be entered as annotations on secured methods, or as access