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>
<title>Overview</title>
</info>
<para>Particularly in the case of web request URI security, sometimes it is more convenient
to assign configuration attributes against every possible secure object invocation. Put
differently, sometimes it is nice to say <literal>ROLE_SOMETHING</literal> is required
by default and only allow certain exceptions to this rule, such as for login, logout and
home pages of an application. There are also other situations where anonymous
authentication would be desired, such as when an auditing interceptor queries the
<classname>SecurityContextHolder</classname> to identify which principal was
responsible for a given operation. Such classes can be authored with more robustness if
they know the <classname>SecurityContextHolder</classname> always contains an
<interfacename>Authentication</interfacename> object, and never
<para>It's generally considered good security practice to adopt a
<quote>deny-by-default</quote> where you explicitly specify what is allowed and
disallow everything else. Defining what is accessible to unauthenticated users is a
similar situation, particularly for web applications. Many sites require that users must
be authenticated for anything other than a few URLs (for example the home and login
pages). In this case it is easiest to define access configuration attributes for these
specific URLs rather than have for every secured resource. Put differently, sometimes it
is nice to say <literal>ROLE_SOMETHING</literal> is required by default and only allow
certain exceptions to this rule, such as for login, logout and home pages of an
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>
</section>
<section xml:id="anonymous-config">
<info>
<title>Configuration</title>
</info>
<para>Spring Security provides three classes that together provide an 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
<para>Anonymous authentication support is provided automatically when using the HTTP
configurain Spring Security 3.0 and can be customized (or disabled) using the
<literal>&lt;anonymous></literal> element. You don't need to configure the beans
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>,
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
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
<interfacename>Authentication</interfacename> held there. The definition of the
filter and authentication provider appears as follows:</para>
@ -50,8 +68,22 @@
</programlisting>
</para>
<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
<literal>userAttribute</literal> is expressed in the form of
so that tokens created by the former are accepted by the latter<footnote>
<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>.
This is the same syntax as used after the equals sign for
<literal>InMemoryDaoImpl</literal>'s <literal>userMap</literal> property.</para>
@ -59,7 +91,7 @@
can have security applied to them. For example:</para>
<para><programlisting>
<![CDATA[
<bean id="filterInvocationInterceptor"
<bean id="filterSecurityInterceptor"
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/>
@ -73,18 +105,31 @@
</security:filter-security-metadata-source>" +
</property>
</bean>]]>
</programlisting>Rounding out the anonymous authentication discussion is the
<literal>AuthenticationTrustResolver</literal> interface, with its corresponding
<literal>AuthenticationTrustResolverImpl</literal> implementation. This interface
</programlisting></para>
</section>
<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
interested classes to take into account this special type of authentication status. The
<classname>ExceptionTranslationFilter</classname> uses this interface in processing
<literal>AccessDeniedException</literal>s. If an
<literal>AccessDeniedException</literal> is thrown, and the authentication is of an
<classname>ExceptionTranslationFilter</classname> uses this interface in processing
<literal>AccessDeniedException</literal>s. If 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
commence the <interfacename>AuthenticationEntryPoint</interfacename> so the principal
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,
basic, digest or some other normal authentication mechanism</para>
always be deemed <quote>authenticated</quote> and never be given an opportunity to login
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>
</chapter>

View File

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

View File

@ -27,17 +27,15 @@
chapter and refresh your memory. The most common approach to verifying an authentication
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
approach used by the <classname>DaoAuthenticationProvider</classname>, which wraps a
<interfacename>UserDetailsService</interfacename> to implement an
<interfacename>AuthenticationProvider</interfacename>. The loaded
<interfacename>UserDetails</interfacename> object - and particularly the
approach used by the <classname>DaoAuthenticationProvider</classname> (see below). The
loaded <interfacename>UserDetails</interfacename> object - and particularly the
<literal>GrantedAuthority</literal>s it contains - will be used when building the
fully populated <interfacename>Authentication</interfacename> object which is returned
from a successful authentication and stored in the
<classname>SecurityContext</classname>. </para>
<para> If you are using the namespace, an instance of
<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
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
@ -76,6 +74,33 @@
concerned about this, because if you forget to register a suitable provider, you'll
simply receive a <literal>ProviderNotFoundException</literal> when an attempt to
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>
<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">
<info><title>DAO Authentication Provider</title></info>
<section xml:id="dao-provider-overview">
<info><title>Overview</title></info>
<para>Spring Security includes a production-quality
<classname>AuthenticationProvider</classname> implementation called
<literal>DaoAuthenticationProvider</literal>. This authentication
provider is compatible with all of the authentication mechanisms that
generate a <literal>UsernamePasswordAuthenticationToken</literal>, and
is probably the most commonly used provider in the framework. Like
most of the other authentication providers, the
DaoAuthenticationProvider leverages a UserDetailsService in order to
lookup the username, password and GrantedAuthority[]s. Unlike most of
the other authentication providers that leverage UserDetailsService,
this authentication provider actually requires the password to be
presented, and the provider will actually evaluate the validity or
otherwise of the password presented in an authentication request
object.</para>
</section>
<section xml:id="dao-provider-config">
<info><title>Configuration</title></info>
<para>Aside from adding DaoAuthenticationProvider to your
ProviderManager list (as discussed at the start of this part of the
reference guide), and ensuring a suitable authentication mechanism is
configured to present a UsernamePasswordAuthenticationToken, the
configuration of the provider itself is rather simple:</para>
<para><programlisting>
<info>
<title>DAO Authentication Provider</title>
</info>
<section xml:id="dao-provider-overview">
<info>
<title>Overview</title>
</info>
<para>Spring Security includes a production-quality
<classname>AuthenticationProvider</classname> implementation called
<literal>DaoAuthenticationProvider</literal>. This authentication provider is
compatible with all of the authentication mechanisms that generate a
<literal>UsernamePasswordAuthenticationToken</literal>, and is probably the most
commonly used provider in the framework. Like most of the other authentication
providers, the DaoAuthenticationProvider leverages a UserDetailsService in order to
lookup the username, password and GrantedAuthority[]s. Unlike most of the other
authentication providers that leverage UserDetailsService, this authentication provider
actually requires the password to be presented, and the provider will actually evaluate
the validity or otherwise of the password presented in an authentication request
object.</para>
</section>
<section xml:id="dao-provider-config">
<info>
<title>Configuration</title>
</info>
<para>Aside from adding DaoAuthenticationProvider to your ProviderManager list (as discussed
at the start of this part of the reference guide), and ensuring a suitable
authentication mechanism is configured to present a UsernamePasswordAuthenticationToken,
the configuration of the provider itself is rather simple:</para>
<para>
<programlisting>
<![CDATA[
<bean id="daoAuthenticationProvider"
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
@ -38,38 +36,33 @@
<property name="saltSource" ref bean="saltSource"/>
<property name="passwordEncoder" ref="passwordEncoder"/>
</bean> ]]>
</programlisting></para>
<para>The <literal>PasswordEncoder</literal> and
<literal>SaltSource</literal> are optional. A
<literal>PasswordEncoder</literal> provides encoding and decoding of
passwords presented in the <interfacename>UserDetails</interfacename> object that
is returned from the configured <interfacename>UserDetailsService</interfacename>.
A <literal>SaltSource</literal> enables the passwords to be populated
with a "salt", which enhances the security of the passwords in the
authentication repository. <literal>PasswordEncoder</literal>
implementations are provided with Spring Security covering MD5, SHA
and cleartext encodings. Two <literal>SaltSource</literal>
implementations are also provided:
<literal>SystemWideSaltSource</literal> which encodes all passwords
with the same salt, and <literal>ReflectionSaltSource</literal>, which
inspects a given property of the returned
<interfacename>UserDetails</interfacename> object to obtain the salt. Please refer
to the JavaDocs for further details on these optional features.</para>
<para>In addition to the properties above, the
<literal>DaoAuthenticationProvider</literal> supports optional caching
of <interfacename>UserDetails</interfacename> objects. The
<literal>UserCache</literal> interface enables the
<literal>DaoAuthenticationProvider</literal> to place a
<interfacename>UserDetails</interfacename> object into the cache, and retrieve it
from the cache upon subsequent authentication attempts for the same
username. By default the <literal>DaoAuthenticationProvider</literal>
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[
</programlisting>
</para>
<para>The <literal>PasswordEncoder</literal> and <literal>SaltSource</literal> are optional.
A <literal>PasswordEncoder</literal> provides encoding and decoding of passwords
presented in the <interfacename>UserDetails</interfacename> object that is returned from
the configured <interfacename>UserDetailsService</interfacename>. A
<literal>SaltSource</literal> enables the passwords to be populated with a "salt",
which enhances the security of the passwords in the authentication repository.
<literal>PasswordEncoder</literal> implementations are provided with Spring Security
covering MD5, SHA and cleartext encodings. Two <literal>SaltSource</literal>
implementations are also provided: <literal>SystemWideSaltSource</literal> which encodes
all passwords with the same salt, and <literal>ReflectionSaltSource</literal>, which
inspects a given property of the returned <interfacename>UserDetails</interfacename>
object to obtain the salt. Please refer to the JavaDocs for further details on these
optional features.</para>
<para>In addition to the properties above, the <literal>DaoAuthenticationProvider</literal>
supports optional caching of <interfacename>UserDetails</interfacename> objects. The
<literal>UserCache</literal> interface enables the
<literal>DaoAuthenticationProvider</literal> to place a
<interfacename>UserDetails</interfacename> object into the cache, and retrieve it
from the cache upon subsequent authentication attempts for the same username. By default
the <literal>DaoAuthenticationProvider</literal> 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"
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="userDetailsService"/>
@ -89,42 +82,19 @@
class="org.springframework.security.core.userdetails.cache.EhCacheBasedUserCache">
<property name="cache" ref="userCacheBackend"/>
</bean>]]>
</programlisting></para>
<para>All Spring Security EH-CACHE implementations (including
<literal>EhCacheBasedUserCache</literal>) require an EH-CACHE
<literal>Cache</literal> object. The <literal>Cache</literal> object
can be obtained from wherever you like, although we recommend you use
Spring's factory classes as shown in the above configuration. If using
Spring's factory classes, please refer to the Spring documentation for
further details on how to optimise the cache storage location, memory
usage, eviction policies, timeouts etc.</para>
<note><para>In the majority of cases, where your application is a stateful web
application, you don't need to use a cache as the user's authentication
information will be stored in the <literal>HttpSession</literal>.
</para></note>
<para>A design decision was made not to support account locking in the
<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>
</programlisting>
</para>
<para>All Spring Security EH-CACHE implementations (including
<literal>EhCacheBasedUserCache</literal>) require an EH-CACHE
<literal>Cache</literal> object. The <literal>Cache</literal> object can be obtained
from wherever you like, although we recommend you use Spring's factory classes as shown
in the above configuration. If using Spring's factory classes, please refer to the
Spring documentation for further details on how to optimise the cache storage location,
memory usage, eviction policies, timeouts etc.</para>
<note>
<para>In the majority of cases, where your application is a stateful web application,
you don't need to use a cache as the user's authentication information will be
stored in the <literal>HttpSession</literal>. </para>
</note>
</section>
</chapter>

View File

@ -113,7 +113,7 @@
<section xml:id="ns-web-xml">
<title><literal>web.xml</literal> Configuration</title>
<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-name>springSecurityFilterChain</filter-name>
<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
data tables</link>. Alternatively, you could configure a Spring Security
<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'/>
<beans:bean id="myUserDetailsService"
@ -332,7 +332,7 @@
<title>Adding HTTP/HTTPS Channel Security</title>
<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
<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>
<intercept-url pattern="/secure/**" access="ROLE_USER" requires-channel="https"/>
<intercept-url pattern="/**" access="ROLE_USER" requires-channel="any"/>
@ -406,14 +406,21 @@
version of a standard namespace filter, such as the
<literal>UsernamePasswordAuthenticationProcessingFilter</literal> which is created by the
<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
do this 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
Spring Security filter implements the Spring <interfacename>Ordered</interfacename>
interface and the filters created by the namespace are sorted during initialization. The
standard Spring Security filters each have an alias in the namespace. The filters, aliases
and namespace elements/attributes which create the filters are shown in <xref
linkend="filter-stack"/>. <table xml:id="filter-stack">
configuration options which are available by using the bean explicitly. How can you do this
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. When the
application context is being created, the filter beans are sorted by the namespace handling
code and the standard Spring Security filters each have an alias in the namespace and a
well-known position.<note>
<para>In previous versions, the sorting took place after the filter instances had been
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>
<tgroup cols="3" align="left">
<thead>
@ -510,10 +517,13 @@
</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
your filter should appear at: <programlisting language="xml"><![CDATA[
<beans:bean id="myFilter" class="com.mycompany.MySpecialAuthenticationFilter">
<custom-filter position="AUTHENTICATION_PROCESSING_FILTER"/>
</beans:bean>
]]></programlisting> You can also use the <literal>after</literal> or <literal>before</literal>
<http>
<custom-filter position="AUTHENTICATION_PROCESSING_FILTER" ref="myFilter" />
</http>
<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
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,
@ -575,12 +585,12 @@
</section>
<section xml:id="ns-method-security">
<title>Method Security</title>
<para>From version 2.0 onwards Spring Security has improved support substantially for adding security to your
service layer methods. It provides support for JSR-250 security
as well as the framework's native <literal>@Secured</literal>
annotation. You can apply security to a single bean, using the
<literal>intercept-methods</literal> element to decorate the bean declaration, or you can
secure multiple beans across the entire service layer using the AspectJ style pointcuts. </para>
<para>From version 2.0 onwards Spring Security has improved support substantially for adding
security to your service layer methods. It provides support for JSR-250 security as well as
the framework's native <literal>@Secured</literal> annotation. You can apply security to a
single bean, using the <literal>intercept-methods</literal> element to decorate the bean
declaration, or you can secure multiple beans across the entire service layer using the
AspectJ style pointcuts. </para>
<section xml:id="ns-global-method">
<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
@ -664,7 +674,7 @@
<para> For method security, you do this by setting the
<literal>access-decision-manager-ref</literal> attribute on
<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>
@ -681,8 +691,9 @@
<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
<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 can't use a custom <classname>AuthenticationManager</classname> if you are using either HTTP or method security
you've used the framework before. If not, it will be covered later, in <link
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
<classname>AuthenticationProvider</classname>s that are used. </para>
<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="remember-me-authentication.xml"/>
<xi:include href="concurrent-sessions.xml"/>
<xi:include href="anon-auth-provider.xml"/>
</part>
<!--
<part xml:id="authentication">
<title>Authentication</title>
<partintro>
@ -138,9 +140,8 @@
</footnote>. </para>
</partintro>
<xi:include href="dao-auth-provider.xml"/>
<xi:include href="anon-auth-provider.xml"/>
<xi:include href="runas-auth-provider.xml"/>
</part>
-->
<part xml:id="authorization">
<title>Authorization</title>
<partintro>
@ -164,7 +165,7 @@
Essentially standalone features which do not have to follow on directly from earlier chapters
-->
<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>
<xi:include href="domain-acls.xml"/>
<xi:include href="preauth.xml"/>
@ -172,6 +173,7 @@
<xi:include href="jaas-auth-provider.xml"/>
<xi:include href="cas-auth-provider.xml"/>
<xi:include href="x509-auth-provider.xml"/>
<xi:include href="runas-auth-provider.xml"/>
</part>
<xi:include href="appendix-db-schema.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
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
important that you understand what they are, even if you don't actually need to directly
interact with them.</para>
important that you understand what they are, even if you don't actually need to interact with
them directly.</para>
<section>
<title> SecurityContextHolder, SecurityContext and Authentication Objects </title>
<para>The most fundamental object is <classname>SecurityContextHolder</classname>. This is
@ -44,13 +44,15 @@
no need to worry about it.</para>
<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
all threads in a Java Virtual Machine to use the same security context. For this situation
you would use the <literal>SecurityContextHolder.MODE_GLOBAL</literal>. Other applications
might want to have threads spawned by the secure thread also assume the same security
identity. This is achieved by using
all threads in a Java Virtual Machine to use the same security context.
<classname>SecurityContextHolder</classname> can be configured with a strategy on startup
to specify how you would like the contex to be stored. For a standalone application you
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
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
the default, but if you do, take a look at the JavaDocs for
<classname>SecurityContextHolder</classname> to learn more.</para>
@ -74,9 +76,9 @@ if (principal instanceof UserDetails) {
}</programlisting>
<para>The object returned by the call to <methodname>getContext()</methodname> is an
instance of the <interfacename>SecurityContext</interfacename> interface. This is the
object that is kept in thread-local storage. Most authentication mechanisms withing Spring
Security return an instance of <interfacename>UserDetails</interfacename> as the principal
as we'll see below. </para>
object that is kept in thread-local storage. As we'll see below, Most authentication
mechanisms withing Spring Security return an instance of
<interfacename>UserDetails</interfacename> as the principal. </para>
</section>
</section>
<section>
@ -109,15 +111,15 @@ if (principal instanceof UserDetails) {
<para> On successful authentication, <interfacename>UserDetails</interfacename> is used to
build the <interfacename>Authentication</interfacename> object that is stored in the
<classname>SecurityContextHolder</classname> (more on this <link
xlink:href="#tech-intro-authentication-mgr">below</link>). The good news is that we provide a
number of <interfacename>UserDetailsService</interfacename> implementations, including one
that uses an in-memory map (<classname>InMemoryDaoImpl</classname>) and another that uses
JDBC (<interfacename>JdbcDaoImpl</interfacename>). Most users tend to write their own,
though, with their implementations often simply sitting on top of an existing Data Access
Object (DAO) that represents their employees, customers, or other users of the application.
Remember the advantage that whatever your <interfacename>UserDetailsService</interfacename>
returns can always be obtained from the <classname>SecurityContextHolder</classname> using
the above code fragment. </para>
xlink:href="#tech-intro-authentication-mgr">below</link>). The good news is that we
provide a number of <interfacename>UserDetailsService</interfacename> implementations,
including one that uses an in-memory map (<classname>InMemoryDaoImpl</classname>) and
another that uses JDBC (<interfacename>JdbcDaoImpl</interfacename>). Most users tend to
write their own, though, with their implementations often simply sitting on top of an
existing Data Access Object (DAO) that represents their employees, customers, or other users
of the application. Remember the advantage that whatever your
<interfacename>UserDetailsService</interfacename> returns can always be obtained from the
<classname>SecurityContextHolder</classname> using the above code fragment. </para>
</section>
<section xml:id="tech-granted-authority">
<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
Spring Security-specific <interfacename>Authentication</interfacename> object, and put it
onto the <classname>SecurityContextHolder</classname>.</para>
<para>
If you're wondering how the <interfacename>AuthenticationManager</interfacename>
manager is implemented in a real world example, we'll look at that in
</para>
<para> If you're wondering how the <interfacename>AuthenticationManager</interfacename>
manager is implemented in a real world example, we'll look at that in </para>
</section>
</section>
</section>
@ -511,10 +511,11 @@ Successfully authenticated. Security context contains: \
<title>What are Configuration Attributes?</title>
<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>.
They are represented by the interface <interfacename>ConfigAttribute</interfacename> within
the framework. They may be simple role names or have more complex meaning, depending on the how
sophisticated the <interfacename>AccessDecisionManager</interfacename> implementation is.
The <classname>AbstractSecurityInterceptor</classname> is configured with a
They are represented by the interface <interfacename>ConfigAttribute</interfacename>
within the framework. They may be simple role names or have more complex meaning,
depending on the how sophisticated the
<interfacename>AccessDecisionManager</interfacename> implementation is. The
<classname>AbstractSecurityInterceptor</classname> is configured with a
<interfacename>SecurityMetadataSource</interfacename> which it uses to look up the
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