Manual formatting.

This commit is contained in:
Luke Taylor 2010-03-03 23:08:05 +00:00
parent ae8027fa47
commit 90caf1bb37
30 changed files with 4145 additions and 3860 deletions

View File

@ -8,17 +8,17 @@
<title>Overview</title> <title>Overview</title>
</info> </info>
<para>It's generally considered good security practice to adopt a <para>It's generally considered good security practice to adopt a
<quote>deny-by-default</quote> where you explicitly specify what is allowed and <quote>deny-by-default</quote> where you explicitly specify what is allowed and disallow
disallow everything else. Defining what is accessible to unauthenticated users is a everything else. Defining what is accessible to unauthenticated users is a similar
similar situation, particularly for web applications. Many sites require that users must situation, particularly for web applications. Many sites require that users must be
be authenticated for anything other than a few URLs (for example the home and login authenticated for anything other than a few URLs (for example the home and login pages).
pages). In this case it is easiest to define access configuration attributes for these In this case it is easiest to define access configuration attributes for these specific
specific URLs rather than have for every secured resource. Put differently, sometimes it URLs rather than have for every secured resource. Put differently, sometimes it is nice
is nice to say <literal>ROLE_SOMETHING</literal> is required by default and only allow to say <literal>ROLE_SOMETHING</literal> is required by default and only allow certain
certain exceptions to this rule, such as for login, logout and home pages of an exceptions to this rule, such as for login, logout and home pages of an application. You
application. You could also omit these pages from the filter chain entirely, thus could also omit these pages from the filter chain entirely, thus bypassing the access
bypassing the access control checks, but this may be undesirable for other reasons, control checks, but this may be undesirable for other reasons, particularly if the pages
particularly if the pages behave differently for authenticated users.</para> behave differently for authenticated users.</para>
<para>This is what we mean by anonymous authentication. Note that there is no real <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 conceptual difference between a user who is <quote>anonymously authenticated</quote> and
an unauthenticated user. Spring Security's anonymous authentication just gives you a an unauthenticated user. Spring Security's anonymous authentication just gives you a
@ -44,18 +44,17 @@
<para>Three classes that together provide the anonymous authentication feature. <para>Three classes that together provide the anonymous authentication feature.
<literal>AnonymousAuthenticationToken</literal> is an implementation of <literal>AnonymousAuthenticationToken</literal> is an implementation of
<interfacename>Authentication</interfacename>, and stores the <interfacename>Authentication</interfacename>, and stores the
<interfacename>GrantedAuthority</interfacename>s which apply to the anonymous <interfacename>GrantedAuthority</interfacename>s which apply to the anonymous principal.
principal. There is a corresponding <literal>AnonymousAuthenticationProvider</literal>, There is a corresponding <literal>AnonymousAuthenticationProvider</literal>, which is
which is chained into the <literal>ProviderManager</literal> so that chained into the <literal>ProviderManager</literal> so that
<literal>AnonymousAuthenticationToken</literal>s are accepted. Finally, there is an <literal>AnonymousAuthenticationToken</literal>s are accepted. Finally, there is an
<classname>AnonymousAuthenticationFilter</classname>, which is chained after the <classname>AnonymousAuthenticationFilter</classname>, which is chained after the normal
normal authentication mechanisms and automatically adds an authentication mechanisms and automatically adds an
<literal>AnonymousAuthenticationToken</literal> to the <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
filter and authentication provider appears as follows:</para> and authentication provider appears as follows:</para>
<para> <para> <programlisting>
<programlisting>
<![CDATA[ <![CDATA[
<bean id="anonymousAuthFilter" <bean id="anonymousAuthFilter"
class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter"> class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
@ -67,32 +66,30 @@
class="org.springframework.security.authentication.AnonymousAuthenticationProvider"> class="org.springframework.security.authentication.AnonymousAuthenticationProvider">
<property name="key" value="foobar"/> <property name="key" value="foobar"/>
</bean>]]> </bean>]]>
</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<footnote><para>The use so that tokens created by the former are accepted by the latter<footnote>
of the <literal>key</literal> property should not be regarded as providing any <para>The use of the <literal>key</literal> property should not be regarded as providing
real security here. It is merely a book-keeping exercise. If you are sharing a any real security here. It is merely a book-keeping exercise. If you are sharing a
<classname>ProviderManager</classname> which contains an <classname>ProviderManager</classname> which contains an
<classname>AnonymousAuthenticationProvider</classname> in a scenario where <classname>AnonymousAuthenticationProvider</classname> in a scenario where it is
it is possible for an authenticating client to construct the possible for an authenticating client to construct the
<interfacename>Authentication</interfacename> object (such as with RMI <interfacename>Authentication</interfacename> object (such as with RMI invocations),
invocations), then a malicious client could submit an then a malicious client could submit an
<classname>AnonymousAuthenticationToken</classname> which it had created <classname>AnonymousAuthenticationToken</classname> which it had created itself
itself (with chosen username and authority list). If the <literal>key</literal> (with chosen username and authority list). If the <literal>key</literal> is
is guessable or can be found out, then the token would be accepted by the guessable or can be found out, then the token would be accepted by the anonymous
anonymous provider. This isn't a problem with normal usage but if you are using provider. This isn't a problem with normal usage but if you are using RMI you would
RMI you would be best to use a customized <classname>ProviderManager</classname> be best to use a customized <classname>ProviderManager</classname> which omits the
which omits the anonymous provider rather than sharing the one you use for your anonymous provider rather than sharing the one you use for your HTTP authentication
HTTP authentication mechanisms.</para></footnote>. The mechanisms.</para>
<literal>userAttribute</literal> is expressed in the form of </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>
<para>As explained earlier, the benefit of anonymous authentication is that all URI patterns <para>As explained earlier, the benefit of anonymous authentication is that all URI patterns
can have security applied to them. For example:</para> can have security applied to them. For example:</para>
<para> <para> <programlisting>
<programlisting>
<![CDATA[ <![CDATA[
<bean id="filterSecurityInterceptor" <bean id="filterSecurityInterceptor"
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor"> class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
@ -108,8 +105,7 @@
</security:filter-security-metadata-source>" + </security:filter-security-metadata-source>" +
</property> </property>
</bean>]]> </bean>]]>
</programlisting> </programlisting> </para>
</para>
</section> </section>
<section xml:id="anonymous-auth-trust-resolver"> <section xml:id="anonymous-auth-trust-resolver">
<title><interfacename>AuthenticationTrustResolver</interfacename></title> <title><interfacename>AuthenticationTrustResolver</interfacename></title>
@ -131,12 +127,12 @@
which is effectively the same thing when defining access controls. This is an example of which is effectively the same thing when defining access controls. This is an example of
the use of the <classname>AuthenticatedVoter</classname> which we will see in the <link the use of the <classname>AuthenticatedVoter</classname> which we will see in the <link
xlink:href="#authz-authenticated-voter">authorization chapter</link>. It uses an xlink:href="#authz-authenticated-voter">authorization chapter</link>. It uses an
<interfacename>AuthenticationTrustResolver</interfacename> to process this <interfacename>AuthenticationTrustResolver</interfacename> to process this particular
particular configuration attribute and grant access to anonymous users. The configuration attribute and grant access to anonymous users. The
<classname>AuthenticatedVoter</classname> approach is more powerful, since it allows <classname>AuthenticatedVoter</classname> approach is more powerful, since it allows you
you to differentiate between anonymous, remember-me and fully-authenticated users. If to differentiate between anonymous, remember-me and fully-authenticated users. If you
you don't need this functionality though, then you can stick with don't need this functionality though, then you can stick with
<literal>ROLE_ANONYMOUS</literal>, which will be processed by Spring Security's <literal>ROLE_ANONYMOUS</literal>, which will be processed by Spring Security's standard
standard <classname>RoleVoter</classname>. </para> <classname>RoleVoter</classname>. </para>
</section> </section>
</chapter> </chapter>

View File

@ -4,16 +4,17 @@
<info> <info>
<title>Security Database Schema</title> <title>Security Database Schema</title>
</info> </info>
<para> There are various database schema used by the framework and this appendix provides a single <para> There are various database schema used by the framework and this appendix provides a
reference point to them all. You only need to provide the tables for the areas of functonality single reference point to them all. You only need to provide the tables for the areas of
you require. </para> functonality you require. </para>
<para> DDL statements are given for the HSQLDB database. You can use these as a guideline for <para> DDL statements are given for the HSQLDB database. You can use these as a guideline for
defining the schema for the database you are using. </para> defining the schema for the database you are using. </para>
<section> <section>
<title>User Schema</title> <title>User Schema</title>
<para> The standard JDBC implementation of the <interfacename>UserDetailsService</interfacename> <para> The standard JDBC implementation of the
(<classname>JdbcDaoImpl</classname>) requires tables to load the password, account status <interfacename>UserDetailsService</interfacename> (<classname>JdbcDaoImpl</classname>)
(enabled or disabled) and a list of authorities (roles) for the user. requires tables to load the password, account status (enabled or disabled) and a list of
authorities (roles) for the user.
<programlisting xml:id="db_schema_users_authorities"> <programlisting xml:id="db_schema_users_authorities">
create table users( create table users(
username varchar_ignorecase(50) not null primary key, username varchar_ignorecase(50) not null primary key,
@ -67,33 +68,35 @@ create table persistent_logins (
<para>There are four tables used by the Spring Security <link xlink:href="#domain-acls" <para>There are four tables used by the Spring Security <link xlink:href="#domain-acls"
>ACL</link> implementation. <orderedlist> >ACL</link> implementation. <orderedlist>
<listitem> <listitem>
<para><literal>acl_sid</literal> stores the security identities recognised by the ACL <para><literal>acl_sid</literal> stores the security identities recognised by the
system. These can be unique principals or authorities which may apply to multiple ACL system. These can be unique principals or authorities which may apply to
principals.</para> multiple principals.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><literal>acl_class</literal> defines the domain object types to which ACLs apply. <para><literal>acl_class</literal> defines the domain object types to which ACLs
The <literal>class</literal> column stores the Java class name of the object. </para> apply. The <literal>class</literal> column stores the Java class name of the
object. </para>
</listitem> </listitem>
<listitem> <listitem>
<para><literal>acl_object_identity</literal> stores the object identity definitions of <para><literal>acl_object_identity</literal> stores the object identity definitions
specific domai objects.</para> of specific domai objects.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><literal>acl_entry</literal> stores the ACL permissions which apply to a specific <para><literal>acl_entry</literal> stores the ACL permissions which apply to a
object identity and security identity.</para> specific object identity and security identity.</para>
</listitem> </listitem>
</orderedlist></para> </orderedlist></para>
<para>It is assumed that the database will auto-generate the primary keys for each of the <para>It is assumed that the database will auto-generate the primary keys for each of the
identities. The <literal>JdbcMutableAclService</literal> has to be able to retrieve these when identities. The <literal>JdbcMutableAclService</literal> has to be able to retrieve
it has created a new row in the <literal>acl_sid</literal> or <literal>acl_class</literal> these when it has created a new row in the <literal>acl_sid</literal> or
tables. It has two properties which define the SQL needed to retrieve these values <literal>acl_class</literal> tables. It has two properties which define the SQL needed
<literal>classIdentityQuery</literal> and <literal>sidIdentityQuery</literal>. Both of these to retrieve these values <literal>classIdentityQuery</literal> and
default to <literal>call identity()</literal></para> <literal>sidIdentityQuery</literal>. Both of these default to <literal>call
identity()</literal></para>
<section> <section>
<title>Hypersonic SQL</title> <title>Hypersonic SQL</title>
<para>The default schema works with the embedded HSQLDB database that is used in unit tests <para>The default schema works with the embedded HSQLDB database that is used in unit
within the tests within the
framework.<programlisting xml:id="dbschema-acl-hsql"> framework.<programlisting xml:id="dbschema-acl-hsql">
create table acl_sid ( create table acl_sid (
id bigint generated by default as identity(start with 100) not null primary key, id bigint generated by default as identity(start with 100) not null primary key,
@ -168,11 +171,11 @@ create table acl_entry(
constraint foreign_fk_4 foreign key(acl_object_identity) constraint foreign_fk_4 foreign key(acl_object_identity)
references acl_object_identity(id), references acl_object_identity(id),
constraint foreign_fk_5 foreign key(sid) references acl_sid(id)); constraint foreign_fk_5 foreign key(sid) references acl_sid(id));
</programlisting> </programlisting> </para>
</para>
<para>You will have to set the <literal>classIdentityQuery</literal> and <para>You will have to set the <literal>classIdentityQuery</literal> and
<literal>sidIdentityQuery</literal> properties of <literal>sidIdentityQuery</literal> properties of
<classname>JdbcMutableAclService</classname> to the following values, respectively: <itemizedlist> <classname>JdbcMutableAclService</classname> to the following values,
respectively: <itemizedlist>
<listitem> <listitem>
<para><literal>select currval(pg_get_serial_sequence('acl_class', <para><literal>select currval(pg_get_serial_sequence('acl_class',
'id'))</literal></para> 'id'))</literal></para>

View File

@ -4,37 +4,37 @@
<info> <info>
<title>The Security Namespace</title> <title>The Security Namespace</title>
</info> </info>
<para> This appendix provides a reference to the elements available in the security namespace and <para> This appendix provides a reference to the elements available in the security namespace
information on the underlying beans they create (a knowledge of the individual classes and how and information on the underlying beans they create (a knowledge of the individual classes
they work together is assumed - you can find more information in the project Javadoc and and how they work together is assumed - you can find more information in the project Javadoc
elsewhere in this document). If you haven't used the namespace before, please read the <link and elsewhere in this document). If you haven't used the namespace before, please read the
xlink:href="#ns-config">introductory chapter</link> on namespace configuration, as this is <link xlink:href="#ns-config">introductory chapter</link> on namespace configuration, as
intended as a supplement to the information there. Using a good quality XML editor while editing this is intended as a supplement to the information there. Using a good quality XML editor
a configuration based on the schema is recommended as this will provide contextual information while editing a configuration based on the schema is recommended as this will provide
on which elements and attributes are available as well as comments explaining their purpose. The contextual information on which elements and attributes are available as well as comments
namespace is written in <link xlink:href="http://www.relaxng.org/">RELAX NG</link> Compact explaining their purpose. The namespace is written in <link
format and later converted into an XSD schema. If you are familiar with this format, you may xlink:href="http://www.relaxng.org/">RELAX NG</link> Compact format and later converted into
wish to examine the <link an XSD schema. If you are familiar with this format, you may wish to examine the <link
xlink:href="https://src.springsource.org/svn/spring-security/trunk/config/src/main/resources/org/springframework/security/config/spring-security-3.0.rnc" xlink:href="https://src.springsource.org/svn/spring-security/trunk/config/src/main/resources/org/springframework/security/config/spring-security-3.0.rnc"
>schema file</link> directly.</para> >schema file</link> directly.</para>
<section xml:id="nsa-http"> <section xml:id="nsa-http">
<title>Web Application Security - the <literal>&lt;http&gt;</literal> Element</title> <title>Web Application Security - the <literal>&lt;http&gt;</literal> Element</title>
<para> The <literal>&lt;http&gt;</literal> element encapsulates the security configuration for <para> The <literal>&lt;http&gt;</literal> element encapsulates the security configuration
the web layer of your application. It creates a <classname>FilterChainProxy</classname> bean for the web layer of your application. It creates a
named "springSecurityFilterChain" which maintains the stack of security filters which make up <classname>FilterChainProxy</classname> bean named "springSecurityFilterChain" which
the web security configuration <footnote> maintains the stack of security filters which make up the web security configuration <footnote>
<para>See the <link xlink:href="#ns-web-xml"> introductory chapter</link> for how to set up <para>See the <link xlink:href="#ns-web-xml"> introductory chapter</link> for how to set
the mapping from your <literal>web.xml</literal></para> up the mapping from your <literal>web.xml</literal></para>
</footnote>. Some core filters are always created and others will be added to the stack </footnote>. Some core filters are always created and others will be added to the stack
depending on the attributes child elements which are present. The positions of the standard depending on the attributes child elements which are present. The positions of the
filters are fixed (see <link xlink:href="#filter-stack">the filter order table</link> in the standard filters are fixed (see <link xlink:href="#filter-stack">the filter order
namespace introduction), removing a common source of errors with previous versions of the table</link> in the namespace introduction), removing a common source of errors with
framework when users had to configure the filter chain explicitly in previous versions of the framework when users had to configure the filter chain
the<classname>FilterChainProxy</classname> bean. You can, of course, still do this if you explicitly in the<classname>FilterChainProxy</classname> bean. You can, of course, still
need full control of the configuration. </para> do this if you need full control of the configuration. </para>
<para> All filters which require a reference to the <para> All filters which require a reference to the
<interfacename>AuthenticationManager</interfacename> will be automatically injected with the <interfacename>AuthenticationManager</interfacename> will be automatically injected with
internal instance created by the namespace configuration (see the <link the internal instance created by the namespace configuration (see the <link
xlink:href="#ns-auth-manager"> introductory chapter</link> for more on the xlink:href="#ns-auth-manager"> introductory chapter</link> for more on the
<interfacename>AuthenticationManager</interfacename>). </para> <interfacename>AuthenticationManager</interfacename>). </para>
<para> The <literal>&lt;http&gt;</literal> namespace block always creates an <para> The <literal>&lt;http&gt;</literal> namespace block always creates an
@ -48,48 +48,53 @@
properties on the core filters. </para> properties on the core filters. </para>
<section xml:id="nsa-servlet-api-provision"> <section xml:id="nsa-servlet-api-provision">
<title><literal>servlet-api-provision</literal></title> <title><literal>servlet-api-provision</literal></title>
<para> Provides versions of <literal>HttpServletRequest</literal> security methods such as <para> Provides versions of <literal>HttpServletRequest</literal> security methods
<literal>isUserInRole()</literal> and <literal>getPrincipal()</literal> which are such as <literal>isUserInRole()</literal> and <literal>getPrincipal()</literal>
implemented by adding a <classname>SecurityContextHolderAwareRequestFilter</classname> which are implemented by adding a
bean to the stack. Defaults to "true". </para> <classname>SecurityContextHolderAwareRequestFilter</classname> bean to the
stack. Defaults to "true". </para>
</section> </section>
<section xml:id="nsa-path-type"> <section xml:id="nsa-path-type">
<title><literal>path-type</literal></title> <title><literal>request-matcher</literal></title>
<para> Controls whether URL patterns are interpreted as ant paths (the default) or regular <para> Defines the <interfacename>RequestMatcher</interfacename> strategy used in
expressions. In practice this sets a particular <interfacename>UrlMatcher</interfacename> the <classname>FilterChainProxy</classname> and the beans created by the
instance on the <classname>FilterChainProxy</classname>. </para> <literal>intercept-url</literal> to match incoming requests. Options are
</section> currently <literal>ant</literal>, <literal>regex</literal> and
<section xml:id="nsa-lowercase-comparisons"> <literal>ciRegex</literal>, for ant, regular-expression and case-insensitive
<title><literal>lowercase-comparisons</literal></title> regular-expression repsectively. A separate instance is created for each
<para> Whether test URLs should be converted to lower case prior to comparing with defined <literal>intercept-url</literal> element using its <literal>pattern</literal>
path patterns. If unspecified, defaults to "true" </para> and <literal>method</literal> attributes (see below). Ant paths are matched
using an <classname>AntPathRequestMatcher</classname> and regular expressions
are matched using a <classname>RegexRequestMatcher</classname>. See the Javadoc
for these classes for more details. Ant paths are the default strategy.</para>
</section> </section>
<section xml:id="nsa-realm"> <section xml:id="nsa-realm">
<title><literal>realm</literal></title> <title><literal>realm</literal></title>
<para> Sets the realm name used for basic authentication (if enabled). Corresponds to the <para> Sets the realm name used for basic authentication (if enabled). Corresponds
<literal>realmName</literal> property on to the <literal>realmName</literal> property on
<classname>BasicAuthenticationEntryPoint</classname>. </para> <classname>BasicAuthenticationEntryPoint</classname>. </para>
</section> </section>
<section xml:id="nsa-entry-point-ref"> <section xml:id="nsa-entry-point-ref">
<title><literal>entry-point-ref</literal></title> <title><literal>entry-point-ref</literal></title>
<para> Normally the <interfacename>AuthenticationEntryPoint</interfacename> used will be set <para> Normally the <interfacename>AuthenticationEntryPoint</interfacename> used
depending on which authentication mechanisms have been configured. This attribute allows will be set depending on which authentication mechanisms have been configured.
this behaviour to be overridden by defining a customized This attribute allows this behaviour to be overridden by defining a customized
<interfacename>AuthenticationEntryPoint</interfacename> bean which will start the <interfacename>AuthenticationEntryPoint</interfacename> bean which will start
authentication process. </para> the authentication process. </para>
</section> </section>
<section xml:id="nsa-access-decision-manager-ref"> <section xml:id="nsa-access-decision-manager-ref">
<title><literal>access-decision-manager-ref</literal></title> <title><literal>access-decision-manager-ref</literal></title>
<para> Optional attribute specifying the ID of the <para> Optional attribute specifying the ID of the
<interfacename>AccessDecisionManager</interfacename> implementation which should be used <interfacename>AccessDecisionManager</interfacename> implementation which should
for authorizing HTTP requests. By default an <classname>AffirmativeBased</classname> be used for authorizing HTTP requests. By default an
implementation is used for with a <classname>RoleVoter</classname> and an <classname>AffirmativeBased</classname> implementation is used for with a
<classname>RoleVoter</classname> and an
<classname>AuthenticatedVoter</classname>. </para> <classname>AuthenticatedVoter</classname>. </para>
</section> </section>
<section xml:id="nsa-access-denied-page"> <section xml:id="nsa-access-denied-page">
<title><literal>access-denied-page</literal></title> <title><literal>access-denied-page</literal></title>
<para> Deprecated in favour of the <literal>access-denied-handler</literal> child element. <para> Deprecated in favour of the <literal>access-denied-handler</literal> child
</para> element. </para>
</section> </section>
<section xml:id="nsa-once-per-request"> <section xml:id="nsa-once-per-request">
<title><literal>once-per-request</literal></title> <title><literal>once-per-request</literal></title>
@ -98,17 +103,18 @@
</section> </section>
<section xml:id="create-session"> <section xml:id="create-session">
<title><literal>create-session</literal></title> <title><literal>create-session</literal></title>
<para> Controls the eagerness with which an HTTP session is created. If not set, defaults to <para> Controls the eagerness with which an HTTP session is created. If not set,
"ifRequired". Other options are "always" and "never". The setting of this attribute affect defaults to "ifRequired". Other options are "always" and "never". The setting of
the <literal>allowSessionCreation</literal> and this attribute affect the <literal>allowSessionCreation</literal> and
<literal>forceEagerSessionCreation</literal> properties of <literal>forceEagerSessionCreation</literal> properties of
<classname>HttpSessionContextIntegrationFilter</classname>. <classname>HttpSessionContextIntegrationFilter</classname>.
<literal>allowSessionCreation</literal> will always be true unless this attribute is set <literal>allowSessionCreation</literal> will always be true unless this
to "never". <literal>forceEagerSessionCreation</literal> is "false" unless it is set to attribute is set to "never". <literal>forceEagerSessionCreation</literal> is
"always". So the default configuration allows session creation but does not force it. The "false" unless it is set to "always". So the default configuration allows
exception is if concurrent session control is enabled, when session creation but does not force it. The exception is if concurrent session
<literal>forceEagerSessionCreation</literal> will be set to true, regardless of what the control is enabled, when <literal>forceEagerSessionCreation</literal> will be
setting is here. Using "never" would then cause an exception during the initialization of set to true, regardless of what the setting is here. Using "never" would then
cause an exception during the initialization of
<classname>HttpSessionContextIntegrationFilter</classname>. </para> <classname>HttpSessionContextIntegrationFilter</classname>. </para>
</section> </section>
</section> </section>
@ -117,89 +123,93 @@
<para> This element allows you to set the <literal>errorPage</literal> property for the <para> This element allows you to set the <literal>errorPage</literal> property for the
default <interfacename>AccessDeniedHandler</interfacename> used by the default <interfacename>AccessDeniedHandler</interfacename> used by the
<classname>ExceptionTranslationFilter</classname>, (using the <classname>ExceptionTranslationFilter</classname>, (using the
<literal>error-page</literal> attribute, or to supply your own implementation using the <literal>error-page</literal> attribute, or to supply your own implementation using
<literal>ref</literal> attribute. This is discussed in more detail in the section on <link the <literal>ref</literal> attribute. This is discussed in more detail in the
xlink:href="#access-denied-handler">the section on <link xlink:href="#access-denied-handler">the
<classname>ExceptionTranslationFilter</classname></link>.</para> <classname>ExceptionTranslationFilter</classname></link>.</para>
</section> </section>
<section> <section>
<title>The <literal>&lt;intercept-url&gt;</literal> Element</title> <title>The <literal>&lt;intercept-url&gt;</literal> Element</title>
<para> This element is used to define the set of URL patterns that the application is <para> This element is used to define the set of URL patterns that the application is
interested in and to configure how they should be handled. It is used to construct the interested in and to configure how they should be handled. It is used to construct
<interfacename>FilterInvocationSecurityMetadataSource</interfacename> used by the the <interfacename>FilterInvocationSecurityMetadataSource</interfacename> used by
<classname>FilterSecurityInterceptor</classname> and to exclude particular patterns from the <classname>FilterSecurityInterceptor</classname> and to exclude particular
the filter chain entirely (by setting the attribute <literal>filters="none"</literal>). It patterns from the filter chain entirely (by setting the attribute
is also responsible for configuring a <classname>ChannelAuthenticationFilter</classname> if <literal>filters="none"</literal>). It is also responsible for configuring a
particular URLs need to be accessed by HTTPS, for example. When matching the specified <classname>ChannelAuthenticationFilter</classname> if particular URLs need to be
patterns against an incoming request, the matching is done in the order in which the accessed by HTTPS, for example. When matching the specified patterns against an
elements are declared. So the most specific matches patterns should come first and the most incoming request, the matching is done in the order in which the elements are
declared. So the most specific matches patterns should come first and the most
general should come last.</para> general should come last.</para>
<section xml:id="nsa-pattern"> <section xml:id="nsa-pattern">
<title><literal>pattern</literal></title> <title><literal>pattern</literal></title>
<para> The pattern which defines the URL path. The content will depend on the <para> The pattern which defines the URL path. The content will depend on the
<literal>path-type</literal> attribute from the containing http element, so will default <literal>path-type</literal> attribute from the containing http element, so will
to ant path syntax. </para> default to ant path syntax. </para>
</section> </section>
<section xml:id="nsa-method"> <section xml:id="nsa-method">
<title><literal>method</literal></title> <title><literal>method</literal></title>
<para> The HTTP Method which will be used in combination with the pattern to match an <para> The HTTP Method which will be used in combination with the pattern to match
incoming request. If omitted, any method will match. If an identical pattern is specified an incoming request. If omitted, any method will match. If an identical pattern
with and without a method, the method-specific match will take precedence.</para> is specified with and without a method, the method-specific match will take
precedence.</para>
</section> </section>
<section xml:id="nsa-access"> <section xml:id="nsa-access">
<title><literal>access</literal></title> <title><literal>access</literal></title>
<para> Lists the access attributes which will be stored in the <para> Lists the access attributes which will be stored in the
<interfacename>FilterInvocationSecurityMetadataSource</interfacename> for the defined URL <interfacename>FilterInvocationSecurityMetadataSource</interfacename> for the
pattern/method combination. This should be a comma-separated list of the security defined URL pattern/method combination. This should be a comma-separated list of
configuration attributes (such as role names). </para> the security configuration attributes (such as role names). </para>
</section> </section>
<section xml:id="nsa-requires-channel"> <section xml:id="nsa-requires-channel">
<title><literal>requires-channel</literal></title> <title><literal>requires-channel</literal></title>
<para> Can be <quote>http</quote> or <quote>https</quote> depending on whether a particular <para> Can be <quote>http</quote> or <quote>https</quote> depending on whether a
URL pattern should be accessed over HTTP or HTTPS respectively. Alternatively the value particular URL pattern should be accessed over HTTP or HTTPS respectively.
<quote>any</quote> can be used when there is no preference. If this attribute is present Alternatively the value <quote>any</quote> can be used when there is no
on any <literal>&lt;intercept-url&gt;</literal> element, then a preference. If this attribute is present on any
<classname>ChannelAuthenticationFilter</classname> will be added to the filter stack and <literal>&lt;intercept-url&gt;</literal> element, then a
its additional dependencies added to the application <classname>ChannelAuthenticationFilter</classname> will be added to the filter
stack and its additional dependencies added to the application
context.<!--See the chapter on <link context.<!--See the chapter on <link
xlink:href="#channel-security-config">channel security</link> for an example xlink:href="#channel-security-config">channel security</link> for an example
configuration using traditional beans. --></para> configuration using traditional beans. --></para>
<para> If a <literal>&lt;port-mappings&gt;</literal> configuration is added, this will be <para> If a <literal>&lt;port-mappings&gt;</literal> configuration is added, this
used to by the <classname>SecureChannelProcessor</classname> and will be used to by the <classname>SecureChannelProcessor</classname> and
<classname>InsecureChannelProcessor</classname> beans to determine the ports used for <classname>InsecureChannelProcessor</classname> beans to determine the ports
redirecting to HTTP/HTTPS. </para> used for redirecting to HTTP/HTTPS. </para>
</section> </section>
<section> <section>
<title><literal>filters</literal></title> <title><literal>filters</literal></title>
<para>Can only take the value <quote>none</quote>. This will cause any matching request to <para>Can only take the value <quote>none</quote>. This will cause any matching
bypass the Spring Security filter chain entirely. None of the rest of the request to bypass the Spring Security filter chain entirely. None of the rest of
<literal>&lt;http></literal> configuration will have any effect on the request and there the <literal>&lt;http></literal> configuration will have any effect on the
will be no security context available for its duration. Access to secured methods during request and there will be no security context available for its duration. Access
the request will fail.</para> to secured methods during the request will fail.</para>
</section> </section>
</section> </section>
<section> <section>
<title>The <literal>&lt;port-mappings&gt;</literal> Element</title> <title>The <literal>&lt;port-mappings&gt;</literal> Element</title>
<para> By default, an instance of <classname>PortMapperImpl</classname> will be added to the <para> By default, an instance of <classname>PortMapperImpl</classname> will be added to
configuration for use in redirecting to secure and insecure URLs. This element can the configuration for use in redirecting to secure and insecure URLs. This element
optionally be used to override the default mappings which that class defines. Each child can optionally be used to override the default mappings which that class defines.
<literal>&lt;port-mapping&gt;</literal> element defines a pair of HTTP:HTTPS ports. The Each child <literal>&lt;port-mapping&gt;</literal> element defines a pair of
default mappings are 80:443 and 8080:8443. An example of overriding these can be found in HTTP:HTTPS ports. The default mappings are 80:443 and 8080:8443. An example of
the <link xlink:href="#ns-requires-channel">namespace introduction</link>. </para> overriding these can be found in the <link xlink:href="#ns-requires-channel"
>namespace introduction</link>. </para>
</section> </section>
<section xml:id="nsa-form-login"> <section xml:id="nsa-form-login">
<title>The <literal>&lt;form-login&gt;</literal> Element</title> <title>The <literal>&lt;form-login&gt;</literal> Element</title>
<para> Used to add an <classname>UsernamePasswordAuthenticationFilter</classname> to the <para> Used to add an <classname>UsernamePasswordAuthenticationFilter</classname> to the
filter stack and an <classname>LoginUrlAuthenticationEntryPoint</classname> to the filter stack and an <classname>LoginUrlAuthenticationEntryPoint</classname> to the
application context to provide authentication on demand. This will always take precedence application context to provide authentication on demand. This will always take
over other namespace-created entry points. If no attributes are supplied, a login page will precedence over other namespace-created entry points. If no attributes are supplied,
be generated automatically at the URL "/spring-security-login" <footnote> a login page will be generated automatically at the URL "/spring-security-login" <footnote>
<para>This feature is really just provided for convenience and is not intended for <para>This feature is really just provided for convenience and is not intended for
production (where a view technology will have been chosen and can be used to render a production (where a view technology will have been chosen and can be used to
customized login page). The class render a customized login page). The class
<classname>DefaultLoginPageGeneratingFilter</classname> is responsible for rendering <classname>DefaultLoginPageGeneratingFilter</classname> is responsible for
the login page and will provide login forms for both normal form login and/or OpenID if rendering the login page and will provide login forms for both normal form login
required.</para> and/or OpenID if required.</para>
</footnote> The behaviour can be customized using the following attributes. </para> </footnote> The behaviour can be customized using the following attributes. </para>
<section> <section>
<title><literal>login-page</literal></title> <title><literal>login-page</literal></title>
@ -211,108 +221,117 @@
<section> <section>
<title><literal>login-processing-url</literal></title> <title><literal>login-processing-url</literal></title>
<para> Maps to the <literal>filterProcessesUrl</literal> property of <para> Maps to the <literal>filterProcessesUrl</literal> property of
<classname>UsernamePasswordAuthenticationFilter</classname>. The default value is <classname>UsernamePasswordAuthenticationFilter</classname>. The default value
"/j_spring_security_check". </para> is "/j_spring_security_check". </para>
</section> </section>
<section> <section>
<title><literal>default-target-url</literal></title> <title><literal>default-target-url</literal></title>
<para>Maps to the <literal>defaultTargetUrl</literal> property of <para>Maps to the <literal>defaultTargetUrl</literal> property of
<classname>UsernamePasswordAuthenticationFilter</classname>. If not set, the default <classname>UsernamePasswordAuthenticationFilter</classname>. If not set, the
value is "/" (the application root). A user will be taken to this URL after logging in, default value is "/" (the application root). A user will be taken to this URL
provided they were not asked to login while attempting to access a secured resource, when after logging in, provided they were not asked to login while attempting to
they will be taken to the originally requested URL. </para> access a secured resource, when they will be taken to the originally requested
URL. </para>
</section> </section>
<section> <section>
<title><literal>always-use-default-target</literal></title> <title><literal>always-use-default-target</literal></title>
<para> If set to "true", the user will always start at the value given by <para> If set to "true", the user will always start at the value given by
<literal>default-target-url</literal>, regardless of how they arrived at the login page. <literal>default-target-url</literal>, regardless of how they arrived at the
Maps to the <literal>alwaysUseDefaultTargetUrl</literal> property of login page. Maps to the <literal>alwaysUseDefaultTargetUrl</literal> property of
<classname>UsernamePasswordAuthenticationFilter</classname>. Default value is "false". <classname>UsernamePasswordAuthenticationFilter</classname>. Default value is
</para> "false". </para>
</section> </section>
<section> <section>
<title><literal>authentication-failure-url</literal></title> <title><literal>authentication-failure-url</literal></title>
<para> Maps to the <literal>authenticationFailureUrl</literal> property of <para> Maps to the <literal>authenticationFailureUrl</literal> property of
<classname>UsernamePasswordAuthenticationFilter</classname>. Defines the URL the browser <classname>UsernamePasswordAuthenticationFilter</classname>. Defines the URL the
will be redirected to on login failure. Defaults to "/spring_security_login?login_error", browser will be redirected to on login failure. Defaults to
which will be automatically handled by the automatic login page generator, re-rendering "/spring_security_login?login_error", which will be automatically handled by the
the login page with an error message. </para> automatic login page generator, re-rendering the login page with an error
message. </para>
</section> </section>
<section> <section>
<title><literal>authentication-success-handler-ref</literal></title> <title><literal>authentication-success-handler-ref</literal></title>
<para>This can be used as an alternative to <literal>default-target-url</literal> and <para>This can be used as an alternative to <literal>default-target-url</literal>
<literal>always-use-default-target</literal>, giving you full control over the and <literal>always-use-default-target</literal>, giving you full control over
navigation flow after a successful authentication. The value should be he name of an the navigation flow after a successful authentication. The value should be he
<interfacename>AuthenticationSuccessHandler</interfacename> bean in the application name of an <interfacename>AuthenticationSuccessHandler</interfacename> bean in
context. </para> the application context. </para>
</section> </section>
<section> <section>
<title><literal>authentication-failure-handler-ref</literal></title> <title><literal>authentication-failure-handler-ref</literal></title>
<para>Can be used as an alternative to <literal>authentication-failure-url</literal>, giving <para>Can be used as an alternative to
you full control over the navigation flow after an authentication failure. The value <literal>authentication-failure-url</literal>, giving you full control over the
should be he name of an <interfacename>AuthenticationFailureHandler</interfacename> bean navigation flow after an authentication failure. The value should be he name of
in the application context. </para> an <interfacename>AuthenticationFailureHandler</interfacename> bean in the
application context. </para>
</section> </section>
</section> </section>
<section xml:id="nsa-http-basic"> <section xml:id="nsa-http-basic">
<title>The <literal>&lt;http-basic&gt;</literal> Element</title> <title>The <literal>&lt;http-basic&gt;</literal> Element</title>
<para> Adds a <classname>BasicAuthenticationFilter</classname> and <para> Adds a <classname>BasicAuthenticationFilter</classname> and
<classname>BasicAuthenticationEntryPoint</classname> to the configuration. The latter will <classname>BasicAuthenticationEntryPoint</classname> to the configuration. The
only be used as the configuration entry point if form-based login is not enabled. </para> latter will only be used as the configuration entry point if form-based login is not
enabled. </para>
</section> </section>
<section xml:id="nsa-remember-me"> <section xml:id="nsa-remember-me">
<title>The <literal>&lt;remember-me&gt;</literal> Element</title> <title>The <literal>&lt;remember-me&gt;</literal> Element</title>
<para> Adds the <classname>RememberMeAuthenticationFilter</classname> to the stack. This in <para> Adds the <classname>RememberMeAuthenticationFilter</classname> to the stack. This
turn will be configured with either a <classname>TokenBasedRememberMeServices</classname>, a in turn will be configured with either a
<classname>PersistentTokenBasedRememberMeServices</classname> or a user-specified bean <classname>TokenBasedRememberMeServices</classname>, a
implementing <interfacename>RememberMeServices</interfacename> depending on the attribute <classname>PersistentTokenBasedRememberMeServices</classname> or a user-specified
settings. </para> bean implementing <interfacename>RememberMeServices</interfacename> depending on the
attribute settings. </para>
<section> <section>
<title><literal>data-source-ref</literal></title> <title><literal>data-source-ref</literal></title>
<para> If this is set, <classname>PersistentTokenBasedRememberMeServices</classname> will be <para> If this is set, <classname>PersistentTokenBasedRememberMeServices</classname>
used and configured with a <classname>JdbcTokenRepositoryImpl</classname> instance. will be used and configured with a
</para> <classname>JdbcTokenRepositoryImpl</classname> instance. </para>
</section> </section>
<section> <section>
<title><literal>token-repository-ref</literal></title> <title><literal>token-repository-ref</literal></title>
<para> Configures a <classname>PersistentTokenBasedRememberMeServices</classname> but allows <para> Configures a <classname>PersistentTokenBasedRememberMeServices</classname>
the use of a custom <interfacename>PersistentTokenRepository</interfacename> bean. </para> but allows the use of a custom
<interfacename>PersistentTokenRepository</interfacename> bean. </para>
</section> </section>
<section> <section>
<title><literal>services-ref</literal></title> <title><literal>services-ref</literal></title>
<para> Allows complete control of the <interfacename>RememberMeServices</interfacename> <para> Allows complete control of the
implementation that will be used by the filter. The value should be the Id of a bean in <interfacename>RememberMeServices</interfacename> implementation that will be
the application context which implements this interface. </para> used by the filter. The value should be the Id of a bean in the application
context which implements this interface. </para>
</section> </section>
<section> <section>
<title><literal>token-repository-ref</literal></title> <title><literal>token-repository-ref</literal></title>
<para> Configures a <classname>PersistentTokenBasedRememberMeServices</classname> but allows <para> Configures a <classname>PersistentTokenBasedRememberMeServices</classname>
the use of a custom <interfacename>PersistentTokenRepository</interfacename> bean. </para> but allows the use of a custom
<interfacename>PersistentTokenRepository</interfacename> bean. </para>
</section> </section>
<section> <section>
<title>The <literal>key</literal> Attribute</title> <title>The <literal>key</literal> Attribute</title>
<para>Maps to the "key" property of <classname>AbstractRememberMeServices</classname>. <para>Maps to the "key" property of
Should be set to a unique value to ensure that remember-me cookies are only valid within <classname>AbstractRememberMeServices</classname>. Should be set to a unique
the one application <footnote> value to ensure that remember-me cookies are only valid within the one
application <footnote>
<para>This doesn't affect the use of <para>This doesn't affect the use of
<classname>PersistentTokenBasedRememberMeServices</classname>, where the tokens are <classname>PersistentTokenBasedRememberMeServices</classname>, where the
stored on the server side.</para> tokens are stored on the server side.</para>
</footnote>. </para> </footnote>. </para>
</section> </section>
<section> <section>
<title><literal>token-validity-seconds</literal></title> <title><literal>token-validity-seconds</literal></title>
<para> Maps to the <literal>tokenValiditySeconds</literal> property of <para> Maps to the <literal>tokenValiditySeconds</literal> property of
<classname>AbstractRememberMeServices</classname>. Specifies the period in seconds for <classname>AbstractRememberMeServices</classname>. Specifies the period in
which the remember-me cookie should be valid. By default it will be valid for 14 days. seconds for which the remember-me cookie should be valid. By default it will be
</para> valid for 14 days. </para>
</section> </section>
<section> <section>
<title><literal>user-service-ref</literal></title> <title><literal>user-service-ref</literal></title>
<para> The remember-me services implementations require access to a <para> The remember-me services implementations require access to a
<interfacename>UserDetailsService</interfacename>, so there has to be one defined in the <interfacename>UserDetailsService</interfacename>, so there has to be one
application context. If there is only one, it will be selected and used automatically by defined in the application context. If there is only one, it will be selected
the namespace configuration. If there are multiple instances, you can specify a bean Id and used automatically by the namespace configuration. If there are multiple
explicitly using this attribute. </para> instances, you can specify a bean Id explicitly using this attribute. </para>
</section> </section>
</section> </section>
<section xml:id="nsa-session-mgmt"> <section xml:id="nsa-session-mgmt">
@ -321,26 +340,29 @@
<classname>SessionManagementFilter</classname> to the filter stack.</para> <classname>SessionManagementFilter</classname> to the filter stack.</para>
<section xml:id="session-fixation-protection"> <section xml:id="session-fixation-protection">
<title><literal>session-fixation-protection</literal></title> <title><literal>session-fixation-protection</literal></title>
<para> Indicates whether an existing session should be invalidated when a user authenticates <para> Indicates whether an existing session should be invalidated when a user
and a new session started. If set to "none" no change will be made. "newSession" will authenticates and a new session started. If set to "none" no change will be
create a new empty session. "migrateSession" will create a new session and copy the made. "newSession" will create a new empty session. "migrateSession" will create
session attributes to the new session. Defaults to "migrateSession".</para> a new session and copy the session attributes to the new session. Defaults to
"migrateSession".</para>
<para> If session fixation protection is enabled, the <para> If session fixation protection is enabled, the
<classname>SessionManagementFilter</classname> is inected with a appropriately <classname>SessionManagementFilter</classname> is inected with a appropriately
configured <classname>DefaultSessionAuthenticationStrategy</classname>. See the Javadoc configured <classname>DefaultSessionAuthenticationStrategy</classname>. See the
for this class for more details. </para> Javadoc for this class for more details. </para>
</section> </section>
</section> </section>
<section xml:id="nsa-concurrent-session-control"> <section xml:id="nsa-concurrent-session-control">
<title>The <literal>&lt;concurrency-control&gt;</literal> Element</title> <title>The <literal>&lt;concurrency-control&gt;</literal> Element</title>
<para> Adds support for concurrent session control, allowing limits to be placed on the number <para> Adds support for concurrent session control, allowing limits to be placed on the
of active sessions a user can have. A <classname>ConcurrentSessionFilter</classname> will be number of active sessions a user can have. A
created, and a <classname>ConcurrentSessionControlStrategy</classname> will be used with the <classname>ConcurrentSessionFilter</classname> will be created, and a
<classname>SessionManagementFilter</classname>. If a <literal>form-login</literal> element <classname>ConcurrentSessionControlStrategy</classname> will be used with the
has been declared, the strategy object will also be injected into the created authentication <classname>SessionManagementFilter</classname>. If a <literal>form-login</literal>
filter. An instance of <interfacename>SessionRegistry</interfacename> (a element has been declared, the strategy object will also be injected into the
<classname>SessionRegistryImpl</classname> instance unless the user wishes to use a custom created authentication filter. An instance of
bean) will be created for use by the strategy.</para> <interfacename>SessionRegistry</interfacename> (a
<classname>SessionRegistryImpl</classname> instance unless the user wishes to use a
custom bean) will be created for use by the strategy.</para>
<section> <section>
<title>The <literal>max-sessions</literal> attribute</title> <title>The <literal>max-sessions</literal> attribute</title>
<para>Maps to the <literal>maximumSessions</literal> property of <para>Maps to the <literal>maximumSessions</literal> property of
@ -348,87 +370,92 @@
</section> </section>
<section> <section>
<title>The <literal>expired-url</literal> attribute</title> <title>The <literal>expired-url</literal> attribute</title>
<para> The URL a user will be redirected to if they attempt to use a session which has been <para> The URL a user will be redirected to if they attempt to use a session which
"expired" by the concurrent session controller because the user has exceeded the number of has been "expired" by the concurrent session controller because the user has
allowed sessions and has logged in again elsewhere. Should be set unless exceeded the number of allowed sessions and has logged in again elsewhere.
<literal>exception-if-maximum-exceeded</literal> is set. If no value is supplied, an Should be set unless <literal>exception-if-maximum-exceeded</literal> is set. If
expiry message will just be written directly back to the response. </para> no value is supplied, an expiry message will just be written directly back to
the response. </para>
</section> </section>
<section> <section>
<title>The <literal>error-if-maximum-exceeded</literal> attribute</title> <title>The <literal>error-if-maximum-exceeded</literal> attribute</title>
<para>If set to "true" a <exceptionname>SessionAuthenticationException</exceptionname> will <para>If set to "true" a
be raised when a user attempts to exceed the maximum allowed number of sessions. The <exceptionname>SessionAuthenticationException</exceptionname> will be raised
when a user attempts to exceed the maximum allowed number of sessions. The
default behaviour is to expire the original session. </para> default behaviour is to expire the original session. </para>
</section> </section>
<section> <section>
<title>The <literal>session-registry-alias</literal> and <title>The <literal>session-registry-alias</literal> and
<literal>session-registry-ref</literal> attributes</title> <literal>session-registry-ref</literal> attributes</title>
<para> The user can supply their own <interfacename>SessionRegistry</interfacename> <para> The user can supply their own <interfacename>SessionRegistry</interfacename>
implementation using the <literal>session-registry-ref</literal> attribute. The other implementation using the <literal>session-registry-ref</literal> attribute. The
concurrent session control beans will be wired up to use it. </para> other concurrent session control beans will be wired up to use it. </para>
<para> It can also be useful to have a reference to the internal session registry for use in <para> It can also be useful to have a reference to the internal session registry
your own beans or an admin interface. You can expose the interal bean using the for use in your own beans or an admin interface. You can expose the interal bean
<literal>session-registry-alias</literal> attribute, giving it a name that you can use using the <literal>session-registry-alias</literal> attribute, giving it a name
elsewhere in your configuration. </para> that you can use elsewhere in your configuration. </para>
</section> </section>
</section> </section>
<section xml:id="nsa-anonymous"> <section xml:id="nsa-anonymous">
<title>The <literal>&lt;anonymous&gt;</literal> Element</title> <title>The <literal>&lt;anonymous&gt;</literal> Element</title>
<para> Adds an <classname>AnonymousAuthenticationFilter</classname> to the stack and an <para> Adds an <classname>AnonymousAuthenticationFilter</classname> to the stack and an
<classname>AnonymousAuthenticationProvider</classname>. Required if you are using the <classname>AnonymousAuthenticationProvider</classname>. Required if you are using
<literal>IS_AUTHENTICATED_ANONYMOUSLY</literal> attribute. </para> the <literal>IS_AUTHENTICATED_ANONYMOUSLY</literal> attribute. </para>
</section> </section>
<section xml:id="nsa-x509"> <section xml:id="nsa-x509">
<title>The <literal>&lt;x509&gt;</literal> Element</title> <title>The <literal>&lt;x509&gt;</literal> Element</title>
<para> Adds support for X.509 authentication. An <para> Adds support for X.509 authentication. An
<classname>X509AuthenticationFilter</classname> will be added to the stack and an <classname>X509AuthenticationFilter</classname> will be added to the stack and an
<classname>Http403ForbiddenEntryPoint</classname> bean will be created. The latter will <classname>Http403ForbiddenEntryPoint</classname> bean will be created. The latter
only be used if no other authentication mechanisms are in use (it's only functionality is to will only be used if no other authentication mechanisms are in use (it's only
return an HTTP 403 error code). A functionality is to return an HTTP 403 error code). A
<classname>PreAuthenticatedAuthenticationProvider</classname> will also be created which <classname>PreAuthenticatedAuthenticationProvider</classname> will also be created
delegates the loading of user authorities to a which delegates the loading of user authorities to a
<interfacename>UserDetailsService</interfacename>. </para> <interfacename>UserDetailsService</interfacename>. </para>
<section> <section>
<title>The <literal>subject-principal-regex</literal> attribute</title> <title>The <literal>subject-principal-regex</literal> attribute</title>
<para> Defines a regular expression which will be used to extract the username from the <para> Defines a regular expression which will be used to extract the username from
certificate (for use with the <interfacename>UserDetailsService</interfacename>). </para> the certificate (for use with the
<interfacename>UserDetailsService</interfacename>). </para>
</section> </section>
<section> <section>
<title>The <literal>user-service-ref</literal> attribute</title> <title>The <literal>user-service-ref</literal> attribute</title>
<para> Allows a specific <interfacename>UserDetailsService</interfacename> to be used with <para> Allows a specific <interfacename>UserDetailsService</interfacename> to be
X.509 in the case where multiple instances are configured. If not set, an attempt will be used with X.509 in the case where multiple instances are configured. If not set,
made to locate a suitable instance automatically and use that. </para> an attempt will be made to locate a suitable instance automatically and use
that. </para>
</section> </section>
</section> </section>
<section xml:id="nsa-openid-login"> <section xml:id="nsa-openid-login">
<title>The <literal>&lt;openid-login&gt;</literal> Element</title> <title>The <literal>&lt;openid-login&gt;</literal> Element</title>
<para> Similar to <literal>&lt;form-login&gt;</literal> and has the same attributes. The <para> Similar to <literal>&lt;form-login&gt;</literal> and has the same attributes. The
default value for <literal>login-processing-url</literal> is default value for <literal>login-processing-url</literal> is
"/j_spring_openid_security_check". An <classname>OpenIDAuthenticationFilter</classname> and "/j_spring_openid_security_check". An
<classname>OpenIDAuthenticationFilter</classname> and
<classname>OpenIDAuthenticationProvider</classname> will be registered. The latter <classname>OpenIDAuthenticationProvider</classname> will be registered. The latter
requires a reference to a <interfacename>UserDetailsService</interfacename>. Again, this can requires a reference to a <interfacename>UserDetailsService</interfacename>. Again,
be specified by Id, using the <literal>user-service-ref</literal> attribute, or will be this can be specified by Id, using the <literal>user-service-ref</literal>
located automatically in the application context. </para> attribute, or will be located automatically in the application context. </para>
</section> </section>
<section xml:id="nsa-logout"> <section xml:id="nsa-logout">
<title>The <literal>&lt;logout&gt;</literal> Element</title> <title>The <literal>&lt;logout&gt;</literal> Element</title>
<para> Adds a <classname>LogoutFilter</classname> to the filter stack. This is configured with <para> Adds a <classname>LogoutFilter</classname> to the filter stack. This is
a <classname>SecurityContextLogoutHandler</classname>. </para> configured with a <classname>SecurityContextLogoutHandler</classname>. </para>
<section> <section>
<title>The <literal>logout-url</literal> attribute</title> <title>The <literal>logout-url</literal> attribute</title>
<para> The URL which will cause a logout (i.e. which will be processed by the filter). <para> The URL which will cause a logout (i.e. which will be processed by the
Defaults to "/j_spring_security_logout". </para> filter). Defaults to "/j_spring_security_logout". </para>
</section> </section>
<section> <section>
<title>The <literal>logout-success-url</literal> attribute</title> <title>The <literal>logout-success-url</literal> attribute</title>
<para> The destination URL which the user will be taken to after logging out. Defaults to <para> The destination URL which the user will be taken to after logging out.
"/". </para> Defaults to "/". </para>
</section> </section>
<section> <section>
<title>The <literal>invalidate-session</literal> attribute</title> <title>The <literal>invalidate-session</literal> attribute</title>
<para> Maps to the <literal>invalidateHttpSession</literal> of the <para> Maps to the <literal>invalidateHttpSession</literal> of the
<classname>SecurityContextLogoutHandler</classname>. Defaults to "true", so the session <classname>SecurityContextLogoutHandler</classname>. Defaults to "true", so the
will be invalidated on logout. </para> session will be invalidated on logout. </para>
</section> </section>
</section> </section>
<section> <section>
@ -436,59 +463,65 @@
<para>This element is used to add a filter to the filter chain. It doesn't create any <para>This element is used to add a filter to the filter chain. It doesn't create any
additional beans but is used to select a bean of type additional beans but is used to select a bean of type
<interfacename>javax.servlet.Filter</interfacename> which is already defined in the <interfacename>javax.servlet.Filter</interfacename> which is already defined in the
appllication context and add that at a particular position in the filter chain maintained by appllication context and add that at a particular position in the filter chain
Spring Security. Full details can be found in the namespace chapter.</para> maintained by Spring Security. Full details can be found in the namespace
chapter.</para>
</section> </section>
</section> </section>
<section> <section>
<title>Authentication Services</title> <title>Authentication Services</title>
<para> Before Spring Security 3.0, an <interfacename>AuthenticationManager</interfacename> was <para> Before Spring Security 3.0, an <interfacename>AuthenticationManager</interfacename>
automatically registered internally. Now you must register one explicitly using the was automatically registered internally. Now you must register one explicitly using the
<literal>&lt;authentication-manager&gt;</literal> element. This creates an instance of <literal>&lt;authentication-manager&gt;</literal> element. This creates an instance of
Spring Security's <classname>ProviderManager</classname> class, which needs to be configured Spring Security's <classname>ProviderManager</classname> class, which needs to be
with a list of one or more <interfacename>AuthenticationProvider</interfacename> instances. configured with a list of one or more
These can either be created using syntax elements provided by the namespace, or they can be <interfacename>AuthenticationProvider</interfacename> instances. These can either be
standard bean definitions, marked for addition to the list using the created using syntax elements provided by the namespace, or they can be standard bean
definitions, marked for addition to the list using the
<literal>authentication-provider</literal> element. </para> <literal>authentication-provider</literal> element. </para>
<section> <section>
<title>The <literal>&lt;authentication-manager&gt;</literal> Element</title> <title>The <literal>&lt;authentication-manager&gt;</literal> Element</title>
<para> Every Spring Security application which uses the namespace must have include this <para> Every Spring Security application which uses the namespace must have include this
element somewhere. It is responsible for registering the element somewhere. It is responsible for registering the
<interfacename>AuthenticationManager</interfacename> which provides authentication <interfacename>AuthenticationManager</interfacename> which provides authentication
services to the application. It also allows you to define an alias name for the internal services to the application. It also allows you to define an alias name for the
instance for use in your own configuration. Its use is described in the internal instance for use in your own configuration. Its use is described in the
<link xlink:href="#ns-auth-manager">namespace introduction</link>. All elements which create <link xlink:href="#ns-auth-manager">namespace introduction</link>. All elements
<interfacename>AuthenticationProvider</interfacename> instances should be children of this which create <interfacename>AuthenticationProvider</interfacename> instances should
element.</para> be children of this element.</para>
<section> <section>
<title>The <literal>&lt;authentication-provider&gt;</literal> Element</title> <title>The <literal>&lt;authentication-provider&gt;</literal> Element</title>
<para> Unless used with a <literal>ref</literal> attribute, this element is shorthand for configuring a <para> Unless used with a <literal>ref</literal> attribute, this element is
<link xlink:href="#core-services-dao-provider"><classname>DaoAuthenticationProvider</classname></link>. shorthand for configuring a <link xlink:href="#core-services-dao-provider"
><classname>DaoAuthenticationProvider</classname></link>.
<classname>DaoAuthenticationProvider</classname> loads user information from a <classname>DaoAuthenticationProvider</classname> loads user information from a
<interfacename>UserDetailsService</interfacename> and compares the username/password <interfacename>UserDetailsService</interfacename> and compares the
combination with the values supplied at login. The username/password combination with the values supplied at login. The
<interfacename>UserDetailsService</interfacename> instance can be defined either by <interfacename>UserDetailsService</interfacename> instance can be defined either
using an available namespace element (<literal>jdbc-user-service</literal> or by using the by using an available namespace element (<literal>jdbc-user-service</literal> or
<literal>user-service-ref</literal> attribute to point to a bean defined elsewhere in by using the <literal>user-service-ref</literal> attribute to point to a bean
the application context). You can find examples of these variations in the <link defined elsewhere in the application context). You can find examples of these
xlink:href="#ns-auth-providers">namespace introduction</link>. </para> variations in the <link xlink:href="#ns-auth-providers">namespace
introduction</link>. </para>
<section> <section>
<title>The <literal>&lt;password-encoder&gt;</literal> Element</title> <title>The <literal>&lt;password-encoder&gt;</literal> Element</title>
<para>Authentication providers can optionally be configured to use a password encoder as <para>Authentication providers can optionally be configured to use a password
described in the <link xlink:href="#ns-password-encoder">namespace introduction</link>. encoder as described in the <link xlink:href="#ns-password-encoder"
This will result in the bean being injected with the appropriate >namespace introduction</link>. This will result in the bean being injected
<interfacename>PasswordEncoder</interfacename> instance, potentially with an with the appropriate <interfacename>PasswordEncoder</interfacename>
accompanying <interfacename>SaltSource</interfacename> bean to provide salt values for instance, potentially with an accompanying
<interfacename>SaltSource</interfacename> bean to provide salt values for
hashing. </para> hashing. </para>
</section> </section>
</section> </section>
<section> <section>
<title>Using <literal>&lt;authentication-provider&gt;</literal> to refer to an <title>Using <literal>&lt;authentication-provider&gt;</literal> to refer to an
<interfacename>AuthenticationProvider</interfacename> Bean</title> <interfacename>AuthenticationProvider</interfacename> Bean</title>
<para> If you have written your own <interfacename>AuthenticationProvider</interfacename> <para> If you have written your own
implementation (or want to configure one of Spring Security's own implementations as a <interfacename>AuthenticationProvider</interfacename> implementation (or want to
traditional bean for some reason, then you can use the following syntax to add it to the configure one of Spring Security's own implementations as a traditional bean for
internal <classname>ProviderManager</classname>'s list: <programlisting><![CDATA[ some reason, then you can use the following syntax to add it to the internal
<classname>ProviderManager</classname>'s list: <programlisting><![CDATA[
<security:authentication-manager> <security:authentication-manager>
<security:authentication-provider ref="myAuthenticationProvider" /> <security:authentication-provider ref="myAuthenticationProvider" />
</security:authentication-manager> </security:authentication-manager>
@ -501,132 +534,144 @@
<title>Method Security</title> <title>Method Security</title>
<section> <section>
<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 the primary means of adding support for securing methods on Spring <para> This element is the primary means of adding support for securing methods on
Security beans. Methods can be secured by the use of annotations (defined at the interface Spring Security beans. Methods can be secured by the use of annotations (defined at
or class level) or by defining a set of pointcuts as child elements, using AspectJ syntax. </para> the interface or class level) or by defining a set of pointcuts as child elements,
<para> Method security uses the same <interfacename>AccessDecisionManager</interfacename> using AspectJ syntax. </para>
configuration as web security, but this can be overridden as explained above <xref <para> Method security uses the same
<interfacename>AccessDecisionManager</interfacename> configuration as web security,
but this can be overridden as explained above <xref
xlink:href="#nsa-access-decision-manager-ref"/>, using the same attribute. </para> xlink:href="#nsa-access-decision-manager-ref"/>, using the same attribute. </para>
<section> <section>
<title>The <literal>secured-annotations</literal> and <literal>jsr250-annotations</literal> <title>The <literal>secured-annotations</literal> and
Attributes</title> <literal>jsr250-annotations</literal> Attributes</title>
<para> Setting these to "true" will enable support for Spring Security's own <para> Setting these to "true" will enable support for Spring Security's own
<literal>@Secured</literal> annotations and JSR-250 annotations, respectively. They are <literal>@Secured</literal> annotations and JSR-250 annotations, respectively.
both disabled by default. Use of JSR-250 annotations also adds a They are both disabled by default. Use of JSR-250 annotations also adds a
<classname>Jsr250Voter</classname> to the <classname>Jsr250Voter</classname> to the
<interfacename>AccessDecisionManager</interfacename>, so you need to make sure you do <interfacename>AccessDecisionManager</interfacename>, so you need to make sure
this if you are using a custom implementation and want to use these annotations. </para> you do this if you are using a custom implementation and want to use these
annotations. </para>
</section> </section>
<section> <section>
<title>Securing Methods using <literal>&lt;protect-pointcut&gt;</literal></title> <title>Securing Methods using <literal>&lt;protect-pointcut&gt;</literal></title>
<para> Rather than defining security attributes on an individual method or class basis using <para> Rather than defining security attributes on an individual method or class
the <literal>@Secured</literal> annotation, you can define cross-cutting security basis using the <literal>@Secured</literal> annotation, you can define
constraints across whole sets of methods and interfaces in your service layer using the cross-cutting security constraints across whole sets of methods and interfaces
<literal>&lt;protect-pointcut&gt;</literal> element. This has two attributes: <itemizedlist> in your service layer using the <literal>&lt;protect-pointcut&gt;</literal>
element. This has two attributes: <itemizedlist>
<listitem> <listitem>
<para><literal>expression</literal> - the pointcut expression</para> <para><literal>expression</literal> - the pointcut expression</para>
</listitem> </listitem>
<listitem> <listitem>
<para><literal>access</literal> - the security attributes which apply</para> <para><literal>access</literal> - the security attributes which apply</para>
</listitem> </listitem>
</itemizedlist> You can find an example in the <link xlink:href="#ns-protect-pointcut" </itemizedlist> You can find an example in the <link
>namespace introduction</link>. </para> xlink:href="#ns-protect-pointcut">namespace introduction</link>. </para>
</section> </section>
<section xml:id="nsa-custom-after-invocation"> <section xml:id="nsa-custom-after-invocation">
<title>The <literal>&lt;after-invocation-provider&gt;</literal> Element</title> <title>The <literal>&lt;after-invocation-provider&gt;</literal> Element</title>
<para> This element can be used to decorate an <para> This element can be used to decorate an
<interfacename>AfterInvocationProvider</interfacename> for use by the security <interfacename>AfterInvocationProvider</interfacename> for use by the security
interceptor maintained by the <literal>&lt;global-method-security&gt;</literal> namespace. interceptor maintained by the <literal>&lt;global-method-security&gt;</literal>
You can define zero or more of these within the <literal>global-method-security</literal> namespace. You can define zero or more of these within the
element, each with a <literal>ref</literal> attribute pointing to an <literal>global-method-security</literal> element, each with a
<literal>ref</literal> attribute pointing to an
<interfacename>AfterInvocationProvider</interfacename> bean instance within your <interfacename>AfterInvocationProvider</interfacename> bean instance within your
application context. </para> application context. </para>
</section> </section>
</section> </section>
<section> <section>
<title>LDAP Namespace Options</title> <title>LDAP Namespace Options</title>
<para> LDAP is covered in some details in <link xlink:href="#ldap">its own chapter</link>. We <para> LDAP is covered in some details in <link xlink:href="#ldap">its own
will expand on that here with some explanation of how the namespace options map to Spring chapter</link>. We will expand on that here with some explanation of how the
beans. The LDAP implementation uses Spring LDAP extensively, so some familiarity with that namespace options map to Spring beans. The LDAP implementation uses Spring LDAP
project's API may be useful. </para> extensively, so some familiarity with that project's API may be useful. </para>
<section> <section>
<title>Defining the LDAP Server using the <literal>&lt;ldap-server&gt;</literal> <title>Defining the LDAP Server using the <literal>&lt;ldap-server&gt;</literal>
Element</title> Element</title>
<para> This element sets up a Spring LDAP <interfacename>ContextSource</interfacename> for <para> This element sets up a Spring LDAP
use by the other LDAP beans, defining the location of the LDAP server and other <interfacename>ContextSource</interfacename> for use by the other LDAP beans,
information (such as a username and password, if it doesn't allow anonymous access) for defining the location of the LDAP server and other information (such as a
connecting to it. It can also be used to create an embedded server for testing. Details of username and password, if it doesn't allow anonymous access) for connecting to
the syntax for both options are covered in the <link xlink:href="#ldap-server">LDAP it. It can also be used to create an embedded server for testing. Details of the
chapter</link>. The actual <interfacename>ContextSource</interfacename> implementation syntax for both options are covered in the <link xlink:href="#ldap-server">LDAP
is <classname>DefaultSpringSecurityContextSource</classname> which extends Spring LDAP's chapter</link>. The actual <interfacename>ContextSource</interfacename>
<classname>LdapContextSource</classname> class. The <literal>manager-dn</literal> and implementation is <classname>DefaultSpringSecurityContextSource</classname>
<literal>manager-password</literal> attributes map to the latter's which extends Spring LDAP's <classname>LdapContextSource</classname> class. The
<literal>userDn</literal> and <literal>password</literal> properties respectively. </para> <literal>manager-dn</literal> and <literal>manager-password</literal> attributes
<para> If you only have one server defined in your application context, the other LDAP map to the latter's <literal>userDn</literal> and <literal>password</literal>
namespace-defined beans will use it automatically. Otherwise, you can give the element an properties respectively. </para>
"id" attribute and refer to it from other namespace beans using the <para> If you only have one server defined in your application context, the other
<literal>server-ref</literal> attribute. This is actually the bean Id of the LDAP namespace-defined beans will use it automatically. Otherwise, you can give
<literal>ContextSource</literal> instance, if you want to use it in other traditional the element an "id" attribute and refer to it from other namespace beans using
Spring beans. </para> the <literal>server-ref</literal> attribute. This is actually the bean Id of the
<literal>ContextSource</literal> instance, if you want to use it in other
traditional Spring beans. </para>
</section> </section>
<section> <section>
<title>The <literal>&lt;ldap-provider&gt;</literal> Element</title> <title>The <literal>&lt;ldap-provider&gt;</literal> Element</title>
<para> This element is shorthand for the creation of an <para> This element is shorthand for the creation of an
<classname>LdapAuthenticationProvider</classname> instance. By default this will be <classname>LdapAuthenticationProvider</classname> instance. By default this will
configured with a <classname>BindAuthenticator</classname> instance and a be configured with a <classname>BindAuthenticator</classname> instance and a
<classname>DefaultAuthoritiesPopulator</classname>. As with all namespace authentication <classname>DefaultAuthoritiesPopulator</classname>. As with all namespace
providers, it must be included as a child of the authentication providers, it must be included as a child of the
<literal>authentication-provider</literal> element.</para> <literal>authentication-provider</literal> element.</para>
<section> <section>
<title>The <literal>user-dn-pattern</literal> Attribute</title> <title>The <literal>user-dn-pattern</literal> Attribute</title>
<para> If your users are at a fixed location in the directory (i.e. you can work out the <para> If your users are at a fixed location in the directory (i.e. you can work
DN directly from the username without doing a directory search), you can use this out the DN directly from the username without doing a directory search), you
attribute to map directly to the DN. It maps directly to the can use this attribute to map directly to the DN. It maps directly to the
<literal>userDnPatterns</literal> property of <literal>userDnPatterns</literal> property of
<classname>AbstractLdapAuthenticator</classname>. </para> <classname>AbstractLdapAuthenticator</classname>. </para>
</section> </section>
<section> <section>
<title>The <literal>user-search-base</literal> and <literal>user-search-filter</literal> <title>The <literal>user-search-base</literal> and
Attributes</title> <literal>user-search-filter</literal> Attributes</title>
<para> If you need to perform a search to locate the user in the directory, then you can <para> If you need to perform a search to locate the user in the directory, then
set these attributes to control the search. The <classname>BindAuthenticator</classname> you can set these attributes to control the search. The
will be configured with a <classname>FilterBasedLdapUserSearch</classname> and the <classname>BindAuthenticator</classname> will be configured with a
attribute values map directly to the first two arguments of that bean's constructor. If <classname>FilterBasedLdapUserSearch</classname> and the attribute values
these attributes aren't set and no <literal>user-dn-pattern</literal> has been supplied map directly to the first two arguments of that bean's constructor. If these
as an alternative, then the default search values of attributes aren't set and no <literal>user-dn-pattern</literal> has been
supplied as an alternative, then the default search values of
<literal>user-search-filter="(uid={0})"</literal> and <literal>user-search-filter="(uid={0})"</literal> and
<literal>user-search-base=""</literal> will be used. </para> <literal>user-search-base=""</literal> will be used. </para>
</section> </section>
<section> <section>
<title><literal>group-search-filter</literal>, <literal>group-search-base</literal>, <title><literal>group-search-filter</literal>,
<literal>group-search-base</literal>,
<literal>group-role-attribute</literal> and <literal>role-prefix</literal> <literal>group-role-attribute</literal> and <literal>role-prefix</literal>
Attributes</title> Attributes</title>
<para> The value of <literal>group-search-base</literal> is mapped to the <para> The value of <literal>group-search-base</literal> is mapped to the
<literal>groupSearchBase</literal> constructor argument of <literal>groupSearchBase</literal> constructor argument of
<classname>DefaultAuthoritiesPopulator</classname> and defaults to "ou=groups". The <classname>DefaultAuthoritiesPopulator</classname> and defaults to
default filter value is "(uniqueMember={0})", which assumes that the entry is of type "ou=groups". The default filter value is "(uniqueMember={0})", which assumes
"groupOfUniqueNames". <literal>group-role-attribute</literal> maps to the that the entry is of type "groupOfUniqueNames".
<literal>groupRoleAttribute</literal> attribute and defaults to "cn". Similarly <literal>group-role-attribute</literal> maps to the
<literal>role-prefix</literal> maps to <literal>rolePrefix</literal> and defaults to <literal>groupRoleAttribute</literal> attribute and defaults to "cn".
"ROLE_". </para> Similarly <literal>role-prefix</literal> maps to
<literal>rolePrefix</literal> and defaults to "ROLE_". </para>
</section> </section>
<section> <section>
<title>The <literal>&lt;password-compare&gt;</literal> Element</title> <title>The <literal>&lt;password-compare&gt;</literal> Element</title>
<para> This is used as child element to <literal>&lt;ldap-provider&gt;</literal> and <para> This is used as child element to <literal>&lt;ldap-provider&gt;</literal>
switches the authentication strategy from <classname>BindAuthenticator</classname> to and switches the authentication strategy from
<classname>PasswordComparisonAuthenticator</classname>. This can optionally be <classname>BindAuthenticator</classname> to
supplied with a <literal>hash</literal> attribute or with a child <classname>PasswordComparisonAuthenticator</classname>. This can optionally
<literal>&lt;password-encoder&gt;</literal> element to hash the password before be supplied with a <literal>hash</literal> attribute or with a child
submitting it to the directory for comparison. </para> <literal>&lt;password-encoder&gt;</literal> element to hash the password
before submitting it to the directory for comparison. </para>
</section> </section>
</section> </section>
<section> <section>
<title>The <literal>&lt;ldap-user-service&gt;</literal> Element</title> <title>The <literal>&lt;ldap-user-service&gt;</literal> Element</title>
<para> This element configures an LDAP <interfacename>UserDetailsService</interfacename>. <para> This element configures an LDAP
The class used is <classname>LdapUserDetailsService</classname> which is a combination of <interfacename>UserDetailsService</interfacename>. The class used is
a <classname>FilterBasedLdapUserSearch</classname> and a <classname>LdapUserDetailsService</classname> which is a combination of a
<classname>DefaultAuthoritiesPopulator</classname>. The attributes it supports have the <classname>FilterBasedLdapUserSearch</classname> and a
same usage as in <literal>&lt;ldap-provider&gt;</literal>. </para> <classname>DefaultAuthoritiesPopulator</classname>. The attributes it supports
have the same usage as in <literal>&lt;ldap-provider&gt;</literal>. </para>
</section> </section>
</section> </section>
</section> </section>

View File

@ -7,11 +7,12 @@
<info> <info>
<title>Authorities</title> <title>Authorities</title>
</info> </info>
<para>As we saw in the <link xlink:href="#tech-granted-authority">technical overview</link>, all <para>As we saw in the <link xlink:href="#tech-granted-authority">technical overview</link>,
<interfacename>Authentication</interfacename> implementations store a list of all <interfacename>Authentication</interfacename> implementations store a list of
<interfacename>GrantedAuthority</interfacename> objects. These represent the authorities <interfacename>GrantedAuthority</interfacename> objects. These represent the authorities
that have been granted to the principal. The <interfacename>GrantedAuthority</interfacename> that have been granted to the principal. The
objects are inserted into the <interfacename>Authentication</interfacename> object by the <interfacename>GrantedAuthority</interfacename> objects are inserted into the
<interfacename>Authentication</interfacename> object by the
<interfacename>AuthenticationManager</interfacename> and are later read by <interfacename>AuthenticationManager</interfacename> and are later read by
<interfacename>AccessDecisionManager</interfacename>s when making authorization <interfacename>AccessDecisionManager</interfacename>s when making authorization
decisions.</para> decisions.</para>
@ -22,74 +23,79 @@
<interfacename>AccessDecisionManager</interfacename>s to obtain a precise <interfacename>AccessDecisionManager</interfacename>s to obtain a precise
<literal>String</literal> representation of the <literal>String</literal> representation of the
<interfacename>GrantedAuthority</interfacename>. By returning a representation as a <interfacename>GrantedAuthority</interfacename>. By returning a representation as a
<literal>String</literal>, a <interfacename>GrantedAuthority</interfacename> can be easily <literal>String</literal>, a <interfacename>GrantedAuthority</interfacename> can be
<quote>read</quote> by most <interfacename>AccessDecisionManager</interfacename>s. If a easily <quote>read</quote> by most
<interfacename>AccessDecisionManager</interfacename>s. If a
<interfacename>GrantedAuthority</interfacename> cannot be precisely represented as a <interfacename>GrantedAuthority</interfacename> cannot be precisely represented as a
<literal>String</literal>, the <interfacename>GrantedAuthority</interfacename> is considered <literal>String</literal>, the <interfacename>GrantedAuthority</interfacename> is
<quote>complex</quote> and <literal>getAuthority()</literal> must return considered <quote>complex</quote> and <literal>getAuthority()</literal> must return
<literal>null</literal>.</para> <literal>null</literal>.</para>
<para>An example of a <quote>complex</quote> <para>An example of a <quote>complex</quote> <interfacename>GrantedAuthority</interfacename>
<interfacename>GrantedAuthority</interfacename> would be an implementation that stores a list would be an implementation that stores a list of operations and authority thresholds
of operations and authority thresholds that apply to different customer account numbers. that apply to different customer account numbers. Representing this complex
Representing this complex <interfacename>GrantedAuthority</interfacename> as a <interfacename>GrantedAuthority</interfacename> as a <literal>String</literal> would be
<literal>String</literal> would be quite difficult, and as a result the quite difficult, and as a result the <literal>getAuthority()</literal> method should
<literal>getAuthority()</literal> method should return <literal>null</literal>. This will return <literal>null</literal>. This will indicate to any
indicate to any <interfacename>AccessDecisionManager</interfacename> that it will need to <interfacename>AccessDecisionManager</interfacename> that it will need to specifically
specifically support the <interfacename>GrantedAuthority</interfacename> implementation in support the <interfacename>GrantedAuthority</interfacename> implementation in order to
order to understand its contents.</para> understand its contents.</para>
<para>Spring Security includes one concrete <interfacename>GrantedAuthority</interfacename> <para>Spring Security includes one concrete <interfacename>GrantedAuthority</interfacename>
implementation, <literal>GrantedAuthorityImpl</literal>. This allows any user-specified implementation, <literal>GrantedAuthorityImpl</literal>. This allows any user-specified
<literal>String</literal> to be converted into a <literal>String</literal> to be converted into a
<interfacename>GrantedAuthority</interfacename>. All <interfacename>GrantedAuthority</interfacename>. All
<classname>AuthenticationProvider</classname>s included with the security architecture use <classname>AuthenticationProvider</classname>s included with the security architecture
<literal>GrantedAuthorityImpl</literal> to populate the use <literal>GrantedAuthorityImpl</literal> to populate the
<interfacename>Authentication</interfacename> object.</para> <interfacename>Authentication</interfacename> object.</para>
</section> </section>
<section xml:id="authz-pre-invocation"> <section xml:id="authz-pre-invocation">
<info> <info>
<title>Pre-Invocation Handling</title> <title>Pre-Invocation Handling</title>
</info> </info>
<para> As we've also seen in the <link xlink:href="#secure-objects">Technical Overview</link> <para> As we've also seen in the <link xlink:href="#secure-objects">Technical
chapter, Spring Security provides interceptors which control access to secure objects such as Overview</link> chapter, Spring Security provides interceptors which control access to
method invocations or web requests. A pre-invocation decision on whether the invocation is secure objects such as method invocations or web requests. A pre-invocation decision on
allowed to proceed is made by the <interfacename>AccessDecisionManager</interfacename>. </para> whether the invocation is allowed to proceed is made by the
<interfacename>AccessDecisionManager</interfacename>. </para>
<section xml:id="authz-access-decision-manager"> <section xml:id="authz-access-decision-manager">
<title>The AccessDecisionManager</title> <title>The AccessDecisionManager</title>
<para>The <interfacename>AccessDecisionManager</interfacename> is called by the <para>The <interfacename>AccessDecisionManager</interfacename> is called by the
<classname>AbstractSecurityInterceptor</classname> and is responsible for making final <classname>AbstractSecurityInterceptor</classname> and is responsible for making
access control decisions. The <interfacename>AccessDecisionManager</interfacename> interface final access control decisions. The
contains three methods: <interfacename>AccessDecisionManager</interfacename> interface contains three
methods:
<programlisting> <programlisting>
void decide(Authentication authentication, Object secureObject, void decide(Authentication authentication, Object secureObject,
List&lt;ConfigAttribute&gt; config) throws AccessDeniedException; List&lt;ConfigAttribute&gt; config) throws AccessDeniedException;
boolean supports(ConfigAttribute attribute); boolean supports(ConfigAttribute attribute);
boolean supports(Class clazz); boolean supports(Class clazz);
</programlisting> </programlisting>
The <interfacename>AccessDecisionManager</interfacename>'s <methodname>decide</methodname> The <interfacename>AccessDecisionManager</interfacename>'s
method is passed all the relevant information it needs in order to make an authorization <methodname>decide</methodname> method is passed all the relevant information it
decision. In particular, passing the secure <literal>Object</literal> enables those needs in order to make an authorization decision. In particular, passing the secure
arguments contained in the actual secure object invocation to be inspected. For example, <literal>Object</literal> enables those arguments contained in the actual secure
let's assume the secure object was a <classname>MethodInvocation</classname>. It would be object invocation to be inspected. For example, let's assume the secure object was a
easy to query the <classname>MethodInvocation</classname> for any <classname>MethodInvocation</classname>. It would be easy to query the
<literal>Customer</literal> argument, and then implement some sort of security logic in <classname>MethodInvocation</classname> for any <literal>Customer</literal>
the <interfacename>AccessDecisionManager</interfacename> to ensure the principal is argument, and then implement some sort of security logic in the
<interfacename>AccessDecisionManager</interfacename> to ensure the principal is
permitted to operate on that customer. Implementations are expected to throw an permitted to operate on that customer. Implementations are expected to throw an
<literal>AccessDeniedException</literal> if access is denied.</para> <literal>AccessDeniedException</literal> if access is denied.</para>
<para>The <literal>supports(ConfigAttribute)</literal> method is called by the <para>The <literal>supports(ConfigAttribute)</literal> method is called by the
<classname>AbstractSecurityInterceptor</classname> at startup time to determine if the <classname>AbstractSecurityInterceptor</classname> at startup time to determine if
<interfacename>AccessDecisionManager</interfacename> can process the passed the <interfacename>AccessDecisionManager</interfacename> can process the passed
<literal>ConfigAttribute</literal>. The <literal>supports(Class)</literal> method is <literal>ConfigAttribute</literal>. The <literal>supports(Class)</literal> method is
called by a security interceptor implementation to ensure the configured called by a security interceptor implementation to ensure the configured
<interfacename>AccessDecisionManager</interfacename> supports the type of secure object <interfacename>AccessDecisionManager</interfacename> supports the type of secure
that the security interceptor will present.</para> object that the security interceptor will present.</para>
</section> </section>
<section xml:id="authz-voting-based"> <section xml:id="authz-voting-based">
<title>Voting-Based AccessDecisionManager Implementations</title> <title>Voting-Based AccessDecisionManager Implementations</title>
<para>Whilst users can implement their own <para>Whilst users can implement their own
<interfacename>AccessDecisionManager</interfacename> to control all aspects of <interfacename>AccessDecisionManager</interfacename> to control all aspects of
authorization, Spring Security includes several authorization, Spring Security includes several
<interfacename>AccessDecisionManager</interfacename> implementations that are based on <interfacename>AccessDecisionManager</interfacename> implementations that are based
voting. <xref linkend="authz-access-voting"/> illustrates the relevant classes.</para> on voting. <xref linkend="authz-access-voting"/> illustrates the relevant
classes.</para>
<figure xml:id="authz-access-voting"> <figure xml:id="authz-access-voting">
<title>Voting Decision Manager</title> <title>Voting Decision Manager</title>
<mediaobject> <mediaobject>
@ -99,87 +105,92 @@
</imageobject> </imageobject>
</mediaobject> </mediaobject>
</figure> </figure>
<para>Using this approach, a series of <interfacename>AccessDecisionVoter</interfacename> <para>Using this approach, a series of
implementations are polled on an authorization decision. The <interfacename>AccessDecisionVoter</interfacename> implementations are polled on an
<interfacename>AccessDecisionManager</interfacename> then decides whether or not to throw authorization decision. The <interfacename>AccessDecisionManager</interfacename>
an <literal>AccessDeniedException</literal> based on its assessment of the votes.</para> then decides whether or not to throw an <literal>AccessDeniedException</literal>
<para>The <interfacename>AccessDecisionVoter</interfacename> interface has three methods: based on its assessment of the votes.</para>
<para>The <interfacename>AccessDecisionVoter</interfacename> interface has three
methods:
<programlisting> <programlisting>
int vote(Authentication authentication, Object object, List&lt;ConfigAttribute&gt; config); int vote(Authentication authentication, Object object, List&lt;ConfigAttribute&gt; config);
boolean supports(ConfigAttribute attribute); boolean supports(ConfigAttribute attribute);
boolean supports(Class clazz); boolean supports(Class clazz);
</programlisting> </programlisting>
Concrete implementations return an <literal>int</literal>, with possible values being Concrete implementations return an <literal>int</literal>, with possible values
reflected in the <interfacename>AccessDecisionVoter</interfacename> static fields being reflected in the <interfacename>AccessDecisionVoter</interfacename> static
<literal>ACCESS_ABSTAIN</literal>, <literal>ACCESS_DENIED</literal> and fields <literal>ACCESS_ABSTAIN</literal>, <literal>ACCESS_DENIED</literal> and
<literal>ACCESS_GRANTED</literal>. A voting implementation will return <literal>ACCESS_GRANTED</literal>. A voting implementation will return
<literal>ACCESS_ABSTAIN</literal> if it has no opinion on an authorization decision. If it <literal>ACCESS_ABSTAIN</literal> if it has no opinion on an authorization decision.
does have an opinion, it must return either <literal>ACCESS_DENIED</literal> or If it does have an opinion, it must return either <literal>ACCESS_DENIED</literal>
<literal>ACCESS_GRANTED</literal>.</para> or <literal>ACCESS_GRANTED</literal>.</para>
<para>There are three concrete <interfacename>AccessDecisionManager</interfacename>s provided <para>There are three concrete <interfacename>AccessDecisionManager</interfacename>s
with Spring Security that tally the votes. The <literal>ConsensusBased</literal> provided with Spring Security that tally the votes. The
implementation will grant or deny access based on the consensus of non-abstain votes. <literal>ConsensusBased</literal> implementation will grant or deny access based on
Properties are provided to control behavior in the event of an equality of votes or if all the consensus of non-abstain votes. Properties are provided to control behavior in
votes are abstain. The <literal>AffirmativeBased</literal> implementation will grant access the event of an equality of votes or if all votes are abstain. The
if one or more <literal>ACCESS_GRANTED</literal> votes were received (i.e. a deny vote will <literal>AffirmativeBased</literal> implementation will grant access if one or more
be ignored, provided there was at least one grant vote). Like the <literal>ACCESS_GRANTED</literal> votes were received (i.e. a deny vote will be
<literal>ConsensusBased</literal> implementation, there is a parameter that controls the ignored, provided there was at least one grant vote). Like the
behavior if all voters abstain. The <literal>UnanimousBased</literal> provider expects <literal>ConsensusBased</literal> implementation, there is a parameter that controls
unanimous <literal>ACCESS_GRANTED</literal> votes in order to grant access, ignoring the behavior if all voters abstain. The <literal>UnanimousBased</literal> provider
abstains. It will deny access if there is any <literal>ACCESS_DENIED</literal> vote. Like expects unanimous <literal>ACCESS_GRANTED</literal> votes in order to grant access,
the other implementations, there is a parameter that controls the behaviour if all voters ignoring abstains. It will deny access if there is any
abstain.</para> <literal>ACCESS_DENIED</literal> vote. Like the other implementations, there is a
parameter that controls the behaviour if all voters abstain.</para>
<para>It is possible to implement a custom <para>It is possible to implement a custom
<interfacename>AccessDecisionManager</interfacename> that tallies votes differently. For <interfacename>AccessDecisionManager</interfacename> that tallies votes differently.
example, votes from a particular <interfacename>AccessDecisionVoter</interfacename> might For example, votes from a particular
receive additional weighting, whilst a deny vote from a particular voter may have a veto <interfacename>AccessDecisionVoter</interfacename> might receive additional
effect.</para> weighting, whilst a deny vote from a particular voter may have a veto effect.</para>
<section xml:id="authz-role-voter"> <section xml:id="authz-role-voter">
<title><classname>RoleVoter</classname></title> <title><classname>RoleVoter</classname></title>
<para> The most commonly used <interfacename>AccessDecisionVoter</interfacename> provided <para> The most commonly used <interfacename>AccessDecisionVoter</interfacename>
with Spring Security is the simple <classname>RoleVoter</classname>, which treats provided with Spring Security is the simple <classname>RoleVoter</classname>,
configuration attributes as simple role names and votes to grant access if the user has which treats configuration attributes as simple role names and votes to grant
been assigned that role.</para> access if the user has been assigned that role.</para>
<para>It will vote if any <interfacename>ConfigAttribute</interfacename> begins with the <para>It will vote if any <interfacename>ConfigAttribute</interfacename> begins with
prefix <literal>ROLE_</literal>. It will vote to grant access if there is a the prefix <literal>ROLE_</literal>. It will vote to grant access if there is a
<interfacename>GrantedAuthority</interfacename> which returns a <interfacename>GrantedAuthority</interfacename> which returns a
<literal>String</literal> representation (via the <literal>getAuthority()</literal> <literal>String</literal> representation (via the
method) exactly equal to one or more <literal>ConfigAttributes</literal> starting with the <literal>getAuthority()</literal> method) exactly equal to one or more
prefix <literal>ROLE_</literal>. If there is no exact match of any <literal>ConfigAttributes</literal> starting with the prefix
<literal>ROLE_</literal>. If there is no exact match of any
<literal>ConfigAttribute</literal> starting with <literal>ROLE_</literal>, the <literal>ConfigAttribute</literal> starting with <literal>ROLE_</literal>, the
<literal>RoleVoter</literal> will vote to deny access. If no <literal>RoleVoter</literal> will vote to deny access. If no
<literal>ConfigAttribute</literal> begins with <literal>ROLE_</literal>, the voter will <literal>ConfigAttribute</literal> begins with <literal>ROLE_</literal>, the
abstain.</para> voter will abstain.</para>
</section> </section>
<section xml:id="authz-authenticated-voter"> <section xml:id="authz-authenticated-voter">
<title><classname>AuthenticatedVoter</classname></title> <title><classname>AuthenticatedVoter</classname></title>
<para> Another voter which we've implicitly seen is the <para> Another voter which we've implicitly seen is the
<classname>AuthenticatedVoter</classname>, which can be used to differentiate between <classname>AuthenticatedVoter</classname>, which can be used to differentiate
anonymous, fully-authenticated and remember-me authenticated users. Many sites allow between anonymous, fully-authenticated and remember-me authenticated users. Many
certain limited access under remember-me authentication, but require a user to confirm sites allow certain limited access under remember-me authentication, but require
their identity by logging in for full access.</para> a user to confirm their identity by logging in for full access.</para>
<para>When we've used the attribute <literal>IS_AUTHENTICATED_ANONYMOUSLY</literal> to grant <para>When we've used the attribute <literal>IS_AUTHENTICATED_ANONYMOUSLY</literal>
anonymous access, this attribute was being processed by the to grant anonymous access, this attribute was being processed by the
<classname>AuthenticatedVoter</classname>. See the Javadoc for this class for more <classname>AuthenticatedVoter</classname>. See the Javadoc for this class for
information. </para> more information. </para>
</section> </section>
<section> <section>
<title>Custom Voters</title> <title>Custom Voters</title>
<para>It is also possible to implement a custom <para>It is also possible to implement a custom
<interfacename>AccessDecisionVoter</interfacename>. Several examples are provided in <interfacename>AccessDecisionVoter</interfacename>. Several examples are
Spring Security unit tests, including <literal>ContactSecurityVoter</literal> and provided in Spring Security unit tests, including
<literal>DenyVoter</literal>. The <literal>ContactSecurityVoter</literal> abstains from <literal>ContactSecurityVoter</literal> and <literal>DenyVoter</literal>. The
voting decisions where a <literal>CONTACT_OWNED_BY_CURRENT_USER</literal> <literal>ContactSecurityVoter</literal> abstains from voting decisions where a
<literal>CONTACT_OWNED_BY_CURRENT_USER</literal>
<literal>ConfigAttribute</literal> is not found. If voting, it queries the <literal>ConfigAttribute</literal> is not found. If voting, it queries the
<classname>MethodInvocation</classname> to extract the owner of the <classname>MethodInvocation</classname> to extract the owner of the
<literal>Contact</literal> object that is subject of the method call. It votes to grant <literal>Contact</literal> object that is subject of the method call. It votes
access if the <literal>Contact</literal> owner matches the principal presented in the to grant access if the <literal>Contact</literal> owner matches the principal
<interfacename>Authentication</interfacename> object. It could have just as easily presented in the <interfacename>Authentication</interfacename> object. It could
compared the <literal>Contact</literal> owner with some have just as easily compared the <literal>Contact</literal> owner with some
<interfacename>GrantedAuthority</interfacename> the <interfacename>GrantedAuthority</interfacename> the
<interfacename>Authentication</interfacename> object presented. All of this is achieved <interfacename>Authentication</interfacename> object presented. All of this is
with relatively few lines of code and demonstrates the flexibility of the authorization achieved with relatively few lines of code and demonstrates the flexibility of
model.</para> the authorization model.</para>
</section> </section>
</section> </section>
</section> </section>
@ -188,43 +199,46 @@ boolean supports(Class clazz);
<title>After Invocation Handling</title> <title>After Invocation Handling</title>
</info> </info>
<para>Whilst the <interfacename>AccessDecisionManager</interfacename> is called by the <para>Whilst the <interfacename>AccessDecisionManager</interfacename> is called by the
<classname>AbstractSecurityInterceptor</classname> before proceeding with the secure object <classname>AbstractSecurityInterceptor</classname> before proceeding with the secure
invocation, some applications need a way of modifying the object actually returned by the object invocation, some applications need a way of modifying the object actually
secure object invocation. Whilst you could easily implement your own AOP concern to achieve returned by the secure object invocation. Whilst you could easily implement your own AOP
this, Spring Security provides a convenient hook that has several concrete implementations concern to achieve this, Spring Security provides a convenient hook that has several
that integrate with its ACL capabilities.</para> concrete implementations that integrate with its ACL capabilities.</para>
<para><xref linkend="authz-after-invocation"/> illustrates Spring Security's <para><xref linkend="authz-after-invocation"/> illustrates Spring Security's
<literal>AfterInvocationManager</literal> and its concrete implementations. <figure <literal>AfterInvocationManager</literal> and its concrete implementations. <figure
xml:id="authz-after-invocation"> xml:id="authz-after-invocation">
<title>After Invocation Implementation</title> <title>After Invocation Implementation</title>
<mediaobject> <mediaobject>
<imageobject> <imageobject>
<imagedata align="center" fileref="images/after-invocation.png" format="PNG" scale="75"/> <imagedata align="center" fileref="images/after-invocation.png" format="PNG"
scale="75"/>
</imageobject> </imageobject>
</mediaobject> </mediaobject>
</figure></para> </figure></para>
<para>Like many other parts of Spring Security, <literal>AfterInvocationManager</literal> has a <para>Like many other parts of Spring Security, <literal>AfterInvocationManager</literal>
single concrete implementation, <literal>AfterInvocationProviderManager</literal>, which polls has a single concrete implementation, <literal>AfterInvocationProviderManager</literal>,
a list of <literal>AfterInvocationProvider</literal>s. Each which polls a list of <literal>AfterInvocationProvider</literal>s. Each
<literal>AfterInvocationProvider</literal> is allowed to modify the return object or throw <literal>AfterInvocationProvider</literal> is allowed to modify the return object or
an <literal>AccessDeniedException</literal>. Indeed multiple providers can modify the object, throw an <literal>AccessDeniedException</literal>. Indeed multiple providers can modify
as the result of the previous provider is passed to the next in the list.</para> the object, as the result of the previous provider is passed to the next in the
<para>Please be aware that if you're using <literal>AfterInvocationManager</literal>, you will list.</para>
still need configuration attributes that allow the <para>Please be aware that if you're using <literal>AfterInvocationManager</literal>, you
will still need configuration attributes that allow the
<classname>MethodSecurityInterceptor</classname>'s <classname>MethodSecurityInterceptor</classname>'s
<interfacename>AccessDecisionManager</interfacename> to allow an operation. If you're using <interfacename>AccessDecisionManager</interfacename> to allow an operation. If you're
the typical Spring Security included <interfacename>AccessDecisionManager</interfacename> using the typical Spring Security included
implementations, having no configuration attributes defined for a particular secure method <interfacename>AccessDecisionManager</interfacename> implementations, having no
invocation will cause each <interfacename>AccessDecisionVoter</interfacename> to abstain from configuration attributes defined for a particular secure method invocation will cause
voting. In turn, if the <interfacename>AccessDecisionManager</interfacename> property each <interfacename>AccessDecisionVoter</interfacename> to abstain from voting. In turn,
if the <interfacename>AccessDecisionManager</interfacename> property
"<literal>allowIfAllAbstainDecisions</literal>" is <literal>false</literal>, an "<literal>allowIfAllAbstainDecisions</literal>" is <literal>false</literal>, an
<literal>AccessDeniedException</literal> will be thrown. You may avoid this potential issue <literal>AccessDeniedException</literal> will be thrown. You may avoid this potential
by either (i) setting "<literal>allowIfAllAbstainDecisions</literal>" to issue by either (i) setting "<literal>allowIfAllAbstainDecisions</literal>" to
<literal>true</literal> (although this is generally not recommended) or (ii) simply ensure <literal>true</literal> (although this is generally not recommended) or (ii) simply
that there is at least one configuration attribute that an ensure that there is at least one configuration attribute that an
<interfacename>AccessDecisionVoter</interfacename> will vote to grant access for. This <interfacename>AccessDecisionVoter</interfacename> will vote to grant access for. This
latter (recommended) approach is usually achieved through a <literal>ROLE_USER</literal> or latter (recommended) approach is usually achieved through a <literal>ROLE_USER</literal>
<literal>ROLE_AUTHENTICATED</literal> configuration attribute.</para> or <literal>ROLE_AUTHENTICATED</literal> configuration attribute.</para>
<!-- TODO: Move to ACL section and add reference here --> <!-- TODO: Move to ACL section and add reference here -->
<!-- <!--
<section xml:id="after-invocation-acl-aware"> <section xml:id="after-invocation-acl-aware">

View File

@ -27,11 +27,10 @@
<title>Configuration</title> <title>Configuration</title>
</info> </info>
<para>To implement HTTP Basic Authentication, you need to add a <para>To implement HTTP Basic Authentication, you need to add a
<literal>BasicAuthenticationFilter</literal> to your filter chain. The <literal>BasicAuthenticationFilter</literal> to your filter chain. The application
application context should contain <literal>BasicAuthenticationFilter</literal> and context should contain <literal>BasicAuthenticationFilter</literal> and its required
its required collaborator:</para> collaborator:</para>
<para> <para> <programlisting language="xml"><![CDATA[
<programlisting language="xml"><![CDATA[
<bean id="basicAuthenticationFilter" <bean id="basicAuthenticationFilter"
class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter"> class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/> <property name="authenticationManager" ref="authenticationManager"/>
@ -42,14 +41,13 @@
class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint"> class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint">
<property name="realmName" value="Name Of Your Realm"/> <property name="realmName" value="Name Of Your Realm"/>
</bean>]]> </bean>]]>
</programlisting> </programlisting> </para>
</para>
<para>The configured <interfacename>AuthenticationManager</interfacename> processes each <para>The configured <interfacename>AuthenticationManager</interfacename> processes each
authentication request. If authentication fails, the configured authentication request. If authentication fails, the configured
<interfacename>AuthenticationEntryPoint</interfacename> will be used to retry <interfacename>AuthenticationEntryPoint</interfacename> will be used to retry the
the authentication process. Usually you will use the filter in combination with a authentication process. Usually you will use the filter in combination with a
<literal>BasicAuthenticationEntryPoint</literal>, which returns a 401 response <literal>BasicAuthenticationEntryPoint</literal>, which returns a 401 response with
with a suitable header to retry HTTP Basic authentication. If authentication is a suitable header to retry HTTP Basic authentication. If authentication is
successful, the resulting <interfacename>Authentication</interfacename> object will successful, the resulting <interfacename>Authentication</interfacename> object will
be placed into the <classname>SecurityContextHolder</classname> as usual.</para> be placed into the <classname>SecurityContextHolder</classname> as usual.</para>
<para>If the authentication event was successful, or authentication was not attempted <para>If the authentication event was successful, or authentication was not attempted
@ -86,8 +84,7 @@
expirationTime: The date and time when the nonce expires, expressed in milliseconds expirationTime: The date and time when the nonce expires, expressed in milliseconds
key: A private key to prevent modification of the nonce token key: A private key to prevent modification of the nonce token
</programlisting> </programlisting> </para>
</para>
<para>The <classname>DigestAuthenticatonEntryPoint</classname> has a property specifying the <para>The <classname>DigestAuthenticatonEntryPoint</classname> has a property specifying the
<literal>key</literal> used for generating the nonce tokens, along with a <literal>key</literal> used for generating the nonce tokens, along with a
<literal>nonceValiditySeconds</literal> property for determining the expiration time <literal>nonceValiditySeconds</literal> property for determining the expiration time
@ -99,9 +96,9 @@
if they disagree on an included value (eg password). In Spring Security implementation, if they disagree on an included value (eg password). In Spring Security implementation,
if the server-generated nonce has merely expired (but the digest was otherwise valid), if the server-generated nonce has merely expired (but the digest was otherwise valid),
the <classname>DigestAuthenticationEntryPoint</classname> will send a the <classname>DigestAuthenticationEntryPoint</classname> will send a
<literal>"stale=true"</literal> header. This tells the user agent there is no need <literal>"stale=true"</literal> header. This tells the user agent there is no need to
to disturb the user (as the password and username etc is correct), but simply to try disturb the user (as the password and username etc is correct), but simply to try again
again using a new nonce.</para> using a new nonce.</para>
<para>An appropriate value for <classname>DigestAuthenticationEntryPoint</classname>'s <para>An appropriate value for <classname>DigestAuthenticationEntryPoint</classname>'s
<literal>nonceValiditySeconds</literal> parameter will depend on your application. <literal>nonceValiditySeconds</literal> parameter will depend on your application.
Extremely secure applications should note that an intercepted authentication header can Extremely secure applications should note that an intercepted authentication header can
@ -120,12 +117,10 @@
<title>Configuration</title> <title>Configuration</title>
<para>Now that we've reviewed the theory, let's see how to use it. To implement HTTP <para>Now that we've reviewed the theory, let's see how to use it. To implement HTTP
Digest Authentication, it is necessary to define Digest Authentication, it is necessary to define
<literal>DigestAuthenticationFilter</literal> in the filter chain. The <literal>DigestAuthenticationFilter</literal> in the filter chain. The application
application context will need to define the context will need to define the <literal>DigestAuthenticationFilter</literal> and
<literal>DigestAuthenticationFilter</literal> and its required its required collaborators:</para>
collaborators:</para> <para> <programlisting><![CDATA[
<para>
<programlisting><![CDATA[
<bean id="digestFilter" class= <bean id="digestFilter" class=
"org.springframework.security.web.authentication.www.DigestAuthenticationFilter"> "org.springframework.security.web.authentication.www.DigestAuthenticationFilter">
<property name="userDetailsService" ref="jdbcDaoImpl"/> <property name="userDetailsService" ref="jdbcDaoImpl"/>
@ -139,11 +134,10 @@
<property name="key" value="acegi"/> <property name="key" value="acegi"/>
<property name="nonceValiditySeconds" value="10"/> <property name="nonceValiditySeconds" value="10"/>
</bean>]]> </bean>]]>
</programlisting> </programlisting> </para>
</para>
<para>The configured <interfacename>UserDetailsService</interfacename> is needed because <para>The configured <interfacename>UserDetailsService</interfacename> is needed because
<literal>DigestAuthenticationFilter</literal> must have direct access to the <literal>DigestAuthenticationFilter</literal> must have direct access to the clear
clear text password of a user. Digest Authentication will NOT work if you are using text password of a user. Digest Authentication will NOT work if you are using
encoded passwords in your DAO. The DAO collaborator, along with the encoded passwords in your DAO. The DAO collaborator, along with the
<literal>UserCache</literal>, are typically shared directly with a <literal>UserCache</literal>, are typically shared directly with a
<classname>DaoAuthenticationProvider</classname>. The <classname>DaoAuthenticationProvider</classname>. The

View File

@ -4,11 +4,11 @@
<section xml:id="cas-overview"> <section xml:id="cas-overview">
<title>Overview</title> <title>Overview</title>
<para>JA-SIG produces an enterprise-wide single sign on system known as CAS. Unlike other <para>JA-SIG produces an enterprise-wide single sign on system known as CAS. Unlike other
initiatives, JA-SIG's Central Authentication Service is open source, widely used, simple to initiatives, JA-SIG's Central Authentication Service is open source, widely used, simple
understand, platform independent, and supports proxy capabilities. Spring Security fully to understand, platform independent, and supports proxy capabilities. Spring Security
supports CAS, and provides an easy migration path from single-application deployments of fully supports CAS, and provides an easy migration path from single-application
Spring Security through to multiple-application deployments secured by an enterprise-wide CAS deployments of Spring Security through to multiple-application deployments secured by an
server.</para> enterprise-wide CAS server.</para>
<para>You can learn more about CAS at <literal>http://www.ja-sig.org/cas</literal>. You will <para>You can learn more about CAS at <literal>http://www.ja-sig.org/cas</literal>. You will
also need to visit this site to download the CAS Server files.</para> also need to visit this site to download the CAS Server files.</para>
</section> </section>
@ -16,28 +16,30 @@
<info> <info>
<title>How CAS Works</title> <title>How CAS Works</title>
</info> </info>
<para>Whilst the CAS web site contains documents that detail the architecture of CAS, we present <para>Whilst the CAS web site contains documents that detail the architecture of CAS, we
the general overview again here within the context of Spring Security. Spring Security 3.0 present the general overview again here within the context of Spring Security. Spring
supports CAS 3. At the time of writing, the CAS server was at version 3.3.</para> Security 3.0 supports CAS 3. At the time of writing, the CAS server was at version
<para>Somewhere in your enterprise you will need to setup a CAS server. The CAS server is simply 3.3.</para>
a standard WAR file, so there isn't anything difficult about setting up your server. Inside <para>Somewhere in your enterprise you will need to setup a CAS server. The CAS server is
the WAR file you will customise the login and other single sign on pages displayed to simply a standard WAR file, so there isn't anything difficult about setting up your
users.</para> server. Inside the WAR file you will customise the login and other single sign on pages
displayed to users.</para>
<para>When deploying a CAS 3.3 server, you will also need to specify an <para>When deploying a CAS 3.3 server, you will also need to specify an
<literal>AuthenticationHandler</literal> in the <literal>AuthenticationHandler</literal> in the
<filename>deployerConfigContext.xml</filename> included with CAS. The <filename>deployerConfigContext.xml</filename> included with CAS. The
<literal>AuthenticationHandler</literal> has a simple method that returns a boolean as to <literal>AuthenticationHandler</literal> has a simple method that returns a boolean as
whether a given set of Credentials is valid. Your <literal>AuthenticationHandler</literal> to whether a given set of Credentials is valid. Your
implementation will need to link into some type of backend authentication repository, such as <literal>AuthenticationHandler</literal> implementation will need to link into some type
an LDAP server or database. CAS itself includes numerous of backend authentication repository, such as an LDAP server or database. CAS itself
<literal>AuthenticationHandler</literal>s out of the box to assist with this. When you includes numerous <literal>AuthenticationHandler</literal>s out of the box to assist
download and deploy the server war file, it is set up to successfully authenticate users who with this. When you download and deploy the server war file, it is set up to
enter a password matching their username, which is useful for testing.</para> successfully authenticate users who enter a password matching their username, which is
useful for testing.</para>
<para>Apart from the CAS server itself, the other key players are of course the secure web <para>Apart from the CAS server itself, the other key players are of course the secure web
applications deployed throughout your enterprise. These web applications are known as applications deployed throughout your enterprise. These web applications are known as
"services". There are two types of services: standard services and proxy services. A proxy "services". There are two types of services: standard services and proxy services. A
service is able to request resources from other services on behalf of the user. This will be proxy service is able to request resources from other services on behalf of the user.
explained more fully later.</para> This will be explained more fully later.</para>
<!-- <!--
<section xml:id="cas-sequence"> <section xml:id="cas-sequence">
<title>Spring Security and CAS Interaction Sequence</title> <title>Spring Security and CAS Interaction Sequence</title>
@ -249,30 +251,28 @@
<title>Configuration of CAS Client</title> <title>Configuration of CAS Client</title>
</info> </info>
<para>The web application side of CAS is made easy due to Spring Security. It is assumed you <para>The web application side of CAS is made easy due to Spring Security. It is assumed you
already know the basics of using Spring Security, so these are not covered again below. We'll already know the basics of using Spring Security, so these are not covered again below.
assume a namespace based configuration is being used and add in the CAS beans as required. </para> We'll assume a namespace based configuration is being used and add in the CAS beans as
<para>You will need to add a <classname>ServiceProperties</classname> bean to your application required. </para>
context. This represents your CAS service:</para> <para>You will need to add a <classname>ServiceProperties</classname> bean to your
<para> application context. This represents your CAS service:</para>
<programlisting><![CDATA[ <para> <programlisting><![CDATA[
<bean id="serviceProperties" <bean id="serviceProperties"
class="org.springframework.security.cas.ServiceProperties"> class="org.springframework.security.cas.ServiceProperties">
<property name="service" <property name="service"
value="https://localhost:8443/cas-sample/j_spring_cas_security_check"/> value="https://localhost:8443/cas-sample/j_spring_cas_security_check"/>
<property name="sendRenew" value="false"/> <property name="sendRenew" value="false"/>
</bean>]]> </bean>]]>
</programlisting> </programlisting> </para>
</para>
<para>The <literal>service</literal> must equal a URL that will be monitored by the <para>The <literal>service</literal> must equal a URL that will be monitored by the
<literal>CasAuthenticationFilter</literal>. The <literal>sendRenew</literal> defaults to <literal>CasAuthenticationFilter</literal>. The <literal>sendRenew</literal> defaults to
false, but should be set to true if your application is particularly sensitive. What this false, but should be set to true if your application is particularly sensitive. What
parameter does is tell the CAS login service that a single sign on login is unacceptable. this parameter does is tell the CAS login service that a single sign on login is
Instead, the user will need to re-enter their username and password in order to gain access to unacceptable. Instead, the user will need to re-enter their username and password in
the service.</para> order to gain access to the service.</para>
<para>The following beans should be configured to commence the CAS authentication process <para>The following beans should be configured to commence the CAS authentication process
(assuming you're using a namespace configuration):</para> (assuming you're using a namespace configuration):</para>
<para> <para> <programlisting><![CDATA[
<programlisting><![CDATA[
<security:http entry-point-ref="casEntryPoint"> <security:http entry-point-ref="casEntryPoint">
... ...
<custom-filter position="FORM_LOGIN_FILTER" ref="myFilter" /> <custom-filter position="FORM_LOGIN_FILTER" ref="myFilter" />
@ -289,21 +289,22 @@
<property name="serviceProperties" ref="serviceProperties"/> <property name="serviceProperties" ref="serviceProperties"/>
</bean> </bean>
]]> ]]>
</programlisting> </programlisting> </para>
</para>
<para> The <classname>CasAuthenticationEntryPoint</classname> should be selected to drive <para> The <classname>CasAuthenticationEntryPoint</classname> should be selected to drive
authentication using <link xlink:href="ns-entry-point-ref" authentication using <link xlink:href="ns-entry-point-ref"
><literal>entry-point-ref</literal></link>. </para> ><literal>entry-point-ref</literal></link>. </para>
<para>The <classname>CasAuthenticationFilter</classname> has very similar properties to the <para>The <classname>CasAuthenticationFilter</classname> has very similar properties to the
<classname>UsernamePasswordAuthenticationFilter</classname> (used for form-based logins). <classname>UsernamePasswordAuthenticationFilter</classname> (used for form-based
</para> logins). </para>
<para>For CAS to operate, the <classname>ExceptionTranslationFilter</classname> must have its <para>For CAS to operate, the <classname>ExceptionTranslationFilter</classname> must have
<literal>authenticationEntryPoint</literal> property set to the its <literal>authenticationEntryPoint</literal> property set to the
<classname>CasAuthenticationEntryPoint</classname> bean.</para> <classname>CasAuthenticationEntryPoint</classname> bean.</para>
<para>The <classname>CasAuthenticationEntryPoint</classname> must refer to the <para>The <classname>CasAuthenticationEntryPoint</classname> must refer to the
<classname>ServiceProperties</classname> bean (discussed above), which provides the URL to the <classname>ServiceProperties</classname> bean (discussed above), which provides the URL
enterprise's CAS login server. This is where the user's browser will be redirected.</para> to the enterprise's CAS login server. This is where the user's browser will be
<para>Next you need to add a <literal>CasAuthenticationProvider</literal> and its collaborators: <programlisting><![CDATA[ redirected.</para>
<para>Next you need to add a <literal>CasAuthenticationProvider</literal> and its
collaborators: <programlisting><![CDATA[
<security:authentication-manager alias="authenticationManager"> <security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="casAuthenticationProvider" /> <security:authentication-provider ref="casAuthenticationProvider" />
</security:authentication-manager> </security:authentication-manager>
@ -327,7 +328,8 @@
</programlisting> The </programlisting> The
<classname>CasAuthenticationProvider</classname> uses a <classname>CasAuthenticationProvider</classname> uses a
<interfacename>UserDetailsService</interfacename> instance to load the authorities for a <interfacename>UserDetailsService</interfacename> instance to load the authorities for a
user, once they have been authentiated by CAS. We've shown a simple in-memory setup here. </para> user, once they have been authentiated by CAS. We've shown a simple in-memory setup
here. </para>
<para>The beans are all reasonable self-explanatory if you refer back to the "How CAS Works" <para>The beans are all reasonable self-explanatory if you refer back to the "How CAS Works"
section.</para> section.</para>
</section> </section>

View File

@ -23,19 +23,18 @@
to HTTPS pages.</para> to HTTPS pages.</para>
<para>If session hijacking is considered too significant a risk for your particular <para>If session hijacking is considered too significant a risk for your particular
application, the only option is to use HTTPS for every request. This means the application, the only option is to use HTTPS for every request. This means the
<literal>jsessionid</literal> is never sent across an insecure channel. You will <literal>jsessionid</literal> is never sent across an insecure channel. You will need to
need to ensure your <literal>web.xml</literal>-defined ensure your <literal>web.xml</literal>-defined <literal>&lt;welcome-file&gt;</literal>
<literal>&lt;welcome-file&gt;</literal> points to an HTTPS location, and the points to an HTTPS location, and the application never directs the user to an HTTP
application never directs the user to an HTTP location. Spring Security provides a location. Spring Security provides a solution to assist with the latter.</para>
solution to assist with the latter.</para>
</section> </section>
<section xml:id="channel-security-config"> <section xml:id="channel-security-config">
<info> <info>
<title>Configuration</title> <title>Configuration</title>
</info> </info>
<para>Channel security is supported by the <link xlink:href="#ns-requires-channel">security <para>Channel security is supported by the <link xlink:href="#ns-requires-channel">security
namespace</link> by means of the <literal>requires-channel</literal> attribute on namespace</link> by means of the <literal>requires-channel</literal> attribute on the
the <literal>&lt;intercept-url&gt;</literal> element and this is the simplest (and <literal>&lt;intercept-url&gt;</literal> element and this is the simplest (and
recommended approach).</para> recommended approach).</para>
<para>To configure channel security explicitly, you would define the following the filter in <para>To configure channel security explicitly, you would define the following the filter in
your application context: <programlisting><![CDATA[ your application context: <programlisting><![CDATA[
@ -75,13 +74,13 @@
<para>The <literal>ChannelProcessingFilter</literal> operates by filtering all web requests <para>The <literal>ChannelProcessingFilter</literal> operates by filtering all web requests
and determining the configuration attributes that apply. It then delegates to the and determining the configuration attributes that apply. It then delegates to the
<literal>ChannelDecisionManager</literal>. The default implementation, <literal>ChannelDecisionManager</literal>. The default implementation,
<literal>ChannelDecisionManagerImpl</literal>, should suffice in most cases. It <literal>ChannelDecisionManagerImpl</literal>, should suffice in most cases. It simply
simply delegates to the list of configured <literal>ChannelProcessor</literal> delegates to the list of configured <literal>ChannelProcessor</literal> instances. The
instances. The attribute <literal>ANY_CHANNEL</literal> can be used to override this attribute <literal>ANY_CHANNEL</literal> can be used to override this behaviour and skip
behaviour and skip a particular URL. Otherwise, a <literal>ChannelProcessor</literal> a particular URL. Otherwise, a <literal>ChannelProcessor</literal> will review the
will review the request, and if it is unhappy with the request (e.g. if it was received request, and if it is unhappy with the request (e.g. if it was received across the
across the incorrect transport protocol), it will perform a redirect, throw an exception incorrect transport protocol), it will perform a redirect, throw an exception or take
or take whatever other action is appropriate.</para> whatever other action is appropriate.</para>
<para>Included with Spring Security are two concrete <literal>ChannelProcessor</literal> <para>Included with Spring Security are two concrete <literal>ChannelProcessor</literal>
implementations: <literal>SecureChannelProcessor</literal> ensures requests with a implementations: <literal>SecureChannelProcessor</literal> ensures requests with a
configuration attribute of <literal>REQUIRES_SECURE_CHANNEL</literal> are received over configuration attribute of <literal>REQUIRES_SECURE_CHANNEL</literal> are received over
@ -93,21 +92,20 @@
simply redirect the request to HTTP and HTTPS as appropriate. Appropriate defaults are simply redirect the request to HTTP and HTTPS as appropriate. Appropriate defaults are
assigned to the <literal>ChannelProcessor</literal> implementations for the assigned to the <literal>ChannelProcessor</literal> implementations for the
configuration attribute keywords they respond to and the configuration attribute keywords they respond to and the
<interfacename>ChannelEntryPoint</interfacename> they delegate to, although you have <interfacename>ChannelEntryPoint</interfacename> they delegate to, although you have the
the ability to override these using the application context.</para> ability to override these using the application context.</para>
<para>Note that the redirections are absolute (eg <para>Note that the redirections are absolute (eg
<literal>http://www.company.com:8080/app/page</literal>), not relative (eg <literal>http://www.company.com:8080/app/page</literal>), not relative (eg
<literal>/app/page</literal>). During testing it was discovered that Internet <literal>/app/page</literal>). During testing it was discovered that Internet Explorer 6
Explorer 6 Service Pack 1 has a bug whereby it does not respond correctly to a Service Pack 1 has a bug whereby it does not respond correctly to a redirection
redirection instruction which also changes the port to use. Accordingly, absolute URLs instruction which also changes the port to use. Accordingly, absolute URLs are used in
are used in conjunction with bug detection logic in the conjunction with bug detection logic in the <classname>PortResolverImpl</classname> that
<classname>PortResolverImpl</classname> that is wired up by default to many Spring is wired up by default to many Spring Security beans. Please refer to the JavaDocs for
Security beans. Please refer to the JavaDocs for <classname>PortResolverImpl</classname> <classname>PortResolverImpl</classname> for further details.</para>
for further details.</para>
<para>You should note that using a secure channel is recommended if usernames and passwords <para>You should note that using a secure channel is recommended if usernames and passwords
are to be kept secure during the login process. If you do decide to use are to be kept secure during the login process. If you do decide to use
<classname>ChannelProcessingFilter</classname> with form-based login, please ensure <classname>ChannelProcessingFilter</classname> with form-based login, please ensure that
that your login page is set to <literal>REQUIRES_SECURE_CHANNEL</literal>, and that the your login page is set to <literal>REQUIRES_SECURE_CHANNEL</literal>, and that the
<literal>LoginUrlAuthenticationEntryPoint.forceHttps</literal> property is <literal>LoginUrlAuthenticationEntryPoint.forceHttps</literal> property is
<literal>true</literal>.</para> <literal>true</literal>.</para>
</section> </section>
@ -118,13 +116,13 @@
<para>Once configured, using the channel security filter is very easy. Simply request pages <para>Once configured, using the channel security filter is very easy. Simply request pages
without regard to the protocol (ie HTTP or HTTPS) or port (eg 80, 8080, 443, 8443 etc). without regard to the protocol (ie HTTP or HTTPS) or port (eg 80, 8080, 443, 8443 etc).
Obviously you'll still need a way of making the initial request (probably via the Obviously you'll still need a way of making the initial request (probably via the
<literal>web.xml</literal> <literal>web.xml</literal> <literal>&lt;welcome-file&gt;</literal> or a well-known home
<literal>&lt;welcome-file&gt;</literal> or a well-known home page URL), but once this is page URL), but once this is done the filter will perform redirects as defined by your
done the filter will perform redirects as defined by your application context.</para> application context.</para>
<para>You can also add your own <literal>ChannelProcessor</literal> implementations to the <para>You can also add your own <literal>ChannelProcessor</literal> implementations to the
<literal>ChannelDecisionManagerImpl</literal>. For example, you might set a <literal>ChannelDecisionManagerImpl</literal>. For example, you might set a
<literal>HttpSession</literal> attribute when a human user is detected via a "enter <literal>HttpSession</literal> attribute when a human user is detected via a "enter the
the contents of this graphic" procedure. Your <literal>ChannelProcessor</literal> would contents of this graphic" procedure. Your <literal>ChannelProcessor</literal> would
respond to say <literal>REQUIRES_HUMAN_USER</literal> configuration attributes and respond to say <literal>REQUIRES_HUMAN_USER</literal> configuration attributes and
redirect to an appropriate entry point to start the human user validation process if the redirect to an appropriate entry point to start the human user validation process if the
<literal>HttpSession</literal> attribute is not currently set.</para> <literal>HttpSession</literal> attribute is not currently set.</para>
@ -133,8 +131,8 @@
designed to handle unauthenticated requests, whilst the latter is designed to handle designed to handle unauthenticated requests, whilst the latter is designed to handle
authenticated requests. The latter therefore has access to the granted authorities of authenticated requests. The latter therefore has access to the granted authorities of
the authenticated principal. In addition, problems detected by a the authenticated principal. In addition, problems detected by a
<literal>ChannelProcessor</literal> will generally cause an HTTP/HTTPS redirection <literal>ChannelProcessor</literal> will generally cause an HTTP/HTTPS redirection so
so its requirements can be met, whilst problems detected by an its requirements can be met, whilst problems detected by an
<interfacename>AccessDecisionVoter</interfacename> will ultimately result in an <interfacename>AccessDecisionVoter</interfacename> will ultimately result in an
<literal>AccessDeniedException</literal> (depending on the governing <literal>AccessDeniedException</literal> (depending on the governing
<interfacename>AccessDecisionManager</interfacename>).</para> <interfacename>AccessDecisionManager</interfacename>).</para>

View File

@ -42,7 +42,7 @@
</info> </info>
<para>Questions and comments on Spring Security are welcome. You can use the Spring <para>Questions and comments on Spring Security are welcome. You can use the Spring
Community Forum web site at <uri xlink:href="http://forum.springsource.org" Community Forum web site at <uri xlink:href="http://forum.springsource.org"
>http://forum.springsource.org</uri> to discuss Spring Security with other users of >http://forum.springsource.org</uri> to discuss Spring Security with other users of the
the framework. Remember to use JIRA for bug reports, as explained above.</para> framework. Remember to use JIRA for bug reports, as explained above.</para>
</section> </section>
</chapter> </chapter>

View File

@ -10,11 +10,11 @@
<para>We've already seen <classname>FilterSecurityInterceptor</classname> briefly when <para>We've already seen <classname>FilterSecurityInterceptor</classname> briefly when
discussing <link xlink:href="#tech-intro-access-control">access-control in discussing <link xlink:href="#tech-intro-access-control">access-control in
general</link>, and we've already used it with the namespace where the general</link>, and we've already used it with the namespace where the
<literal>&lt;intercept-url></literal> elements are combined to configure it <literal>&lt;intercept-url></literal> elements are combined to configure it internally.
internally. Now we'll see how to explicitly configure it for use with a Now we'll see how to explicitly configure it for use with a
<classname>FilterChainProxy</classname>, along with its companion filter <classname>FilterChainProxy</classname>, along with its companion filter
<classname>ExceptionTranslationFilter</classname>. A typical configuration example <classname>ExceptionTranslationFilter</classname>. A typical configuration example is
is shown below: <programlisting language="xml"><![CDATA[ shown below: <programlisting language="xml"><![CDATA[
<bean id="filterSecurityInterceptor" <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"/>
@ -31,33 +31,31 @@
<interfacename>AuthenticationManager</interfacename> and an <interfacename>AuthenticationManager</interfacename> and an
<interfacename>AccessDecisionManager</interfacename>. It is also supplied with <interfacename>AccessDecisionManager</interfacename>. It is also supplied with
configuration attributes that apply to different HTTP URL requests. Refer back to <link configuration attributes that apply to different HTTP URL requests. Refer back to <link
xlink:href="#tech-intro-config-attributes">the original discussion on these</link> xlink:href="#tech-intro-config-attributes">the original discussion on these</link> in
in the technical introduction.</para> the technical introduction.</para>
<para>The <classname>FilterSecurityInterceptor</classname> can be configured with <para>The <classname>FilterSecurityInterceptor</classname> can be configured with
configuration attributes in two ways. The first, which is shown above, is using the configuration attributes in two ways. The first, which is shown above, is using the
<literal>&lt;filter-security-metadata-source&gt;</literal> namespace element. This <literal>&lt;filter-security-metadata-source&gt;</literal> namespace element. This is
is similar to the <literal>&lt;filter-chain-map&gt;</literal> used to configure a similar to the <literal>&lt;filter-chain-map&gt;</literal> used to configure a
<classname>FilterChainProxy</classname> but the <classname>FilterChainProxy</classname> but the <literal>&lt;intercept-url&gt;</literal>
<literal>&lt;intercept-url&gt;</literal> child elements only use the child elements only use the <literal>pattern</literal> and <literal>access</literal>
<literal>pattern</literal> and <literal>access</literal> attributes. Commas are used attributes. Commas are used to delimit the different configuration attributes that apply
to delimit the different configuration attributes that apply to each HTTP URL. The to each HTTP URL. The second option is to write your own
second option is to write your own
<interfacename>SecurityMetadataSource</interfacename>, but this is beyond the scope of <interfacename>SecurityMetadataSource</interfacename>, but this is beyond the scope of
this document. Irrespective of the approach used, the this document. Irrespective of the approach used, the
<interfacename>SecurityMetadataSource</interfacename> is responsible for returning a <interfacename>SecurityMetadataSource</interfacename> is responsible for returning a
<literal>List&lt;ConfigAttribute&gt;</literal> containing all of the configuration <literal>List&lt;ConfigAttribute&gt;</literal> containing all of the configuration
attributes associated with a single secure HTTP URL.</para> attributes associated with a single secure HTTP URL.</para>
<para>It should be noted that the <para>It should be noted that the
<literal>FilterSecurityInterceptor.setSecurityMetadataSource()</literal> method <literal>FilterSecurityInterceptor.setSecurityMetadataSource()</literal> method actually
actually expects an instance of expects an instance of <interfacename>FilterSecurityMetadataSource</interfacename>. This
<interfacename>FilterSecurityMetadataSource</interfacename>. This is a marker is a marker interface which subclasses
interface which subclasses <interfacename>SecurityMetadataSource</interfacename>. It <interfacename>SecurityMetadataSource</interfacename>. It simply denotes the
simply denotes the <interfacename>SecurityMetadataSource</interfacename> understands <interfacename>SecurityMetadataSource</interfacename> understands
<classname>FilterInvocation</classname>s. In the interests of simplicity we'll <classname>FilterInvocation</classname>s. In the interests of simplicity we'll continue
continue to refer to the to refer to the <interfacename>FilterInvocationSecurityMetadataSource</interfacename> as
<interfacename>FilterInvocationSecurityMetadataSource</interfacename> as a a <interfacename>SecurityMetadataSource</interfacename>, as the distinction is of little
<interfacename>SecurityMetadataSource</interfacename>, as the distinction is of relevance to most users.</para>
little relevance to most users.</para>
<para>The <interfacename>SecurityMetadataSource</interfacename> created by the namespace <para>The <interfacename>SecurityMetadataSource</interfacename> created by the namespace
syntax obtains the configuration attributes for a particular syntax obtains the configuration attributes for a particular
<classname>FilterInvocation</classname> by matching the request URL against the <classname>FilterInvocation</classname> by matching the request URL against the
@ -101,8 +99,7 @@
--> -->
</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 <para>The <classname>ExceptionTranslationFilter</classname> sits above the
<classname>FilterSecurityInterceptor</classname> in the security filter stack. It <classname>FilterSecurityInterceptor</classname> in the security filter stack. It
doesn't do any actual security enforcement itself, but handles exceptions thrown by the doesn't do any actual security enforcement itself, but handles exceptions thrown by the
@ -128,10 +125,10 @@
<para> The <interfacename>AuthenticationEntryPoint</interfacename> will be called if the <para> The <interfacename>AuthenticationEntryPoint</interfacename> will be called if the
user requests a secure HTTP resource but they are not authenticated. An appropriate user requests a secure HTTP resource but they are not authenticated. An appropriate
<exceptionname>AuthenticationException</exceptionname> or <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 one we've used here is <classname>LoginUrlAuthenticationEntryPoint</classname>, The one we've used here is <classname>LoginUrlAuthenticationEntryPoint</classname>,
which redirects the request to a different URL (typically a login page). The actual 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 implementation used will depend on the authentication mechanism you want to be used
@ -153,32 +150,31 @@
<para>If an <exceptionname>AccessDeniedException</exceptionname> is thrown and a user <para>If an <exceptionname>AccessDeniedException</exceptionname> is thrown and a user
has already been authenticated, then this means that an operation has been attempted has already been authenticated, then this means that an operation has been attempted
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
the <interfacename>AccessDeniedHandler</interfacename>. By default, an <interfacename>AccessDeniedHandler</interfacename>. By default, an
<classname>AccessDeniedHandlerImpl</classname> is used, which just sends a 403 <classname>AccessDeniedHandlerImpl</classname> is used, which just sends a 403
(Forbidden) response to the client. Alternatively you can configure an instance (Forbidden) response to the client. Alternatively you can configure an instance
explicitly (as in the above example) and set an error page URL which it will explicitly (as in the above example) and set an error page URL which it will
forwards the request to <footnote> forwards the request to <footnote>
<para>We use a forward so that the SecurityContextHolder still contains details <para>We use a forward so that the SecurityContextHolder still contains details of
of the principal, which may be useful for displaying to the user. In old the principal, which may be useful for displaying to the user. In old releases
releases of Spring Security we relied upon the servlet container to handle a of Spring Security we relied upon the servlet container to handle a 403 error
403 error message, which lacked this useful contextual information.</para> message, which lacked this useful contextual information.</para>
</footnote>. This can be a simple <quote>access denied</quote> page, such as a JSP, </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 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> can implement the interface yourself and use your own implementation. </para>
<para>It's also possible to supply a custom <para>It's also possible to supply a custom
<interfacename>AccessDeniedHandler</interfacename> when you're using the <interfacename>AccessDeniedHandler</interfacename> when you're using the namespace
namespace to configure your application. See <link to configure your application. See <link xlink:href="#nsa-access-denied-handler">the
xlink:href="#nsa-access-denied-handler">the namespace appendix</link> for more namespace appendix</link> for more details.</para>
details.</para>
</section> </section>
</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> We covered the purpose of this all-important filter in the <link <para> We covered the purpose of this all-important filter in the <link
xlink:href="#tech-intro-sec-context-persistence">Technical Overview</link> chapter xlink:href="#tech-intro-sec-context-persistence">Technical Overview</link> chapter so
so you might want to re-read that section at this point. Let's first take a look at how you might want to re-read that section at this point. Let's first take a look at how you
you would configure it for use with a <classname>FilterChainProxy</classname>. A basic would configure it for use with a <classname>FilterChainProxy</classname>. A basic
configuration only requires the bean itself <programlisting><![CDATA[ configuration only requires the bean itself <programlisting><![CDATA[
<bean id="securityContextPersistenceFilter" <bean id="securityContextPersistenceFilter"
class="org.springframework.security.web.context.SecurityContextPersistenceFilter"/> class="org.springframework.security.web.context.SecurityContextPersistenceFilter"/>
@ -208,16 +204,16 @@ public interface SecurityContextRepository {
<classname>HttpSessionSecurityContextRepository</classname>, which stores the <classname>HttpSessionSecurityContextRepository</classname>, which stores the
security context as an <interfacename>HttpSession</interfacename> attribute <footnote> security context as an <interfacename>HttpSession</interfacename> attribute <footnote>
<para>In Spring Security 2.0 and earlier, this filter was called <para>In Spring Security 2.0 and earlier, this filter was called
<classname>HttpSessionContextIntegrationFilter</classname> and performed <classname>HttpSessionContextIntegrationFilter</classname> and performed all the
all the work of storing the context was performed by the filter itself. If work of storing the context was performed by the filter itself. If you were
you were familiar with this class, then most of the configuration options familiar with this class, then most of the configuration options which were
which were available can now be found on available can now be found on
<classname>HttpSessionSecurityContextRepository</classname>. </para> <classname>HttpSessionSecurityContextRepository</classname>. </para>
</footnote>. The most important configuration parameter for this implementation is </footnote>. The most important configuration parameter for this implementation is
the <literal>allowSessionCreation</literal> property, which defaults to the <literal>allowSessionCreation</literal> property, which defaults to
<literal>true</literal>, thus allowing the class to create a session if it needs <literal>true</literal>, thus allowing the class to create a session if it needs one
one to store the security context for an authenticated user (it won't create one to store the security context for an authenticated user (it won't create one unless
unless authentication has taken place and the contents of the security context have 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 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[ to <literal>false</literal>: <programlisting language="xml"><![CDATA[
<bean id="securityContextPersistenceFilter" <bean id="securityContextPersistenceFilter"
@ -243,16 +239,16 @@ class="org.springframework.security.web.context.SecurityContextPersistenceFilter
something that will allow a user to authenticate. This filter is the most commonly used 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> 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 <para>For historical reasons, prior to Spring Security 3.0, this filter was called
<classname>AuthenticationProcessingFilter</classname> and the entry point <classname>AuthenticationProcessingFilter</classname> and the entry point was called
was called <classname>AuthenticationProcessingFilterEntryPoint</classname>. <classname>AuthenticationProcessingFilterEntryPoint</classname>. Since the framework
Since the framework now supports many different forms of authentication, they now supports many different forms of authentication, they have both been given more
have both been given more specific names in 3.0.</para> specific names in 3.0.</para>
</footnote>. It also provides the implementation used by the </footnote>. It also provides the implementation used by the
<literal>&lt;form-login&gt;</literal> element from the namespace. There are three <literal>&lt;form-login&gt;</literal> element from the namespace. There are three stages
stages required to configure it. <orderedlist> required to configure it. <orderedlist>
<listitem> <listitem>
<para>Configure a <classname>LoginUrlAuthenticationEntryPoint</classname> with <para>Configure a <classname>LoginUrlAuthenticationEntryPoint</classname> with the
the URL of the login page, just as we did above, and set it on the URL of the login page, just as we did above, and set it on the
<classname>ExceptionTranslationFilter</classname>. </para> <classname>ExceptionTranslationFilter</classname>. </para>
</listitem> </listitem>
<listitem> <listitem>
@ -260,17 +256,17 @@ class="org.springframework.security.web.context.SecurityContextPersistenceFilter
</listitem> </listitem>
<listitem> <listitem>
<para>Configure an instance of <para>Configure an instance of
<classname>UsernamePasswordAuthenticationFilter</classname> in the <classname>UsernamePasswordAuthenticationFilter</classname> in the application
application context</para> context</para>
</listitem> </listitem>
<listitem> <listitem>
<para>Add the filter bean to your filter chain proxy (making sure you pay <para>Add the filter bean to your filter chain proxy (making sure you pay attention
attention to the order). <!-- TODO: link --></para> to the order). <!-- TODO: link --></para>
</listitem> </listitem>
</orderedlist> The login form simply contains <literal>j_username</literal> and </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 <literal>j_password</literal> input fields, and posts to the URL that is monitored by
by the filter (by default this is <literal>/j_spring_security_check</literal>). The the filter (by default this is <literal>/j_spring_security_check</literal>). The basic
basic filter configuration looks something like this: <programlisting><![CDATA[ filter configuration looks something like this: <programlisting><![CDATA[
<bean id="authenticationFilter" class= <bean id="authenticationFilter" class=
"org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"> "org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/> <property name="authenticationManager" ref="authenticationManager"/>
@ -280,38 +276,37 @@ class="org.springframework.security.web.context.SecurityContextPersistenceFilter
<section xml:id="form-login-flow-handling"> <section xml:id="form-login-flow-handling">
<title>Application Flow on Authentication Success and Failure</title> <title>Application Flow on Authentication Success and Failure</title>
<para> The filter calls the configured <para> The filter calls the configured
<interfacename>AuthenticationManager</interfacename> to process each <interfacename>AuthenticationManager</interfacename> to process each authentication
authentication request. The destination following a successful authentication or an request. The destination following a successful authentication or an authentication
authentication failure is controlled by the failure is controlled by the
<interfacename>AuthenticationSuccessHandler</interfacename> and <interfacename>AuthenticationSuccessHandler</interfacename> and
<interfacename>AuthenticationFailureHandler</interfacename> strategy interfaces, <interfacename>AuthenticationFailureHandler</interfacename> strategy interfaces,
respectively. The filter has properties which allow you to set these so you can respectively. The filter has properties which allow you to set these so you can
customize the behaviour completely <footnote> customize the behaviour completely <footnote>
<para>In versions prior to 3.0, the application flow at this point had evolved <para>In versions prior to 3.0, the application flow at this point had evolved to a
to a stage was controlled by a mix of properties on this class and strategy stage was controlled by a mix of properties on this class and strategy plugins.
plugins. The decision was made for 3.0 to refactor the code to make these The decision was made for 3.0 to refactor the code to make these two strategies
two strategies entirely responsible. </para> entirely responsible. </para>
</footnote>. Some standard implementations are supplied such as </footnote>. Some standard implementations are supplied such as
<classname>SimpleUrlAuthenticationSuccessHandler</classname>, <classname>SimpleUrlAuthenticationSuccessHandler</classname>,
<classname>SavedRequestAwareAuthenticationSuccessHandler</classname>, <classname>SavedRequestAwareAuthenticationSuccessHandler</classname>,
<classname>SimpleUrlAuthenticationFailureHandler</classname> and <classname>SimpleUrlAuthenticationFailureHandler</classname> and
<classname>ExceptionMappingAuthenticationFailureHandler</classname>. Have a look <classname>ExceptionMappingAuthenticationFailureHandler</classname>. Have a look at
at the Javadoc for these classes to see how they work. </para> the Javadoc for these classes to see how they work. </para>
<para>If authentication is successful, the resulting <para>If authentication is successful, the resulting
<interfacename>Authentication</interfacename> object will be placed into the <interfacename>Authentication</interfacename> object will be placed into the
<classname>SecurityContextHolder</classname>. The configured <classname>SecurityContextHolder</classname>. The configured
<interfacename>AuthenticationSuccessHandler</interfacename> will then be called <interfacename>AuthenticationSuccessHandler</interfacename> will then be called to
to either redirect or forward the user to the appropriate destination. By default a either redirect or forward the user to the appropriate destination. By default a
<classname>SavedRequestAwareAuthenticationSuccessHandler</classname> is used, <classname>SavedRequestAwareAuthenticationSuccessHandler</classname> is used, which
which means that the user will be redirected to the original destination they means that the user will be redirected to the original destination they requested
requested before they were asked to login. <note> before they were asked to login. <note>
<para> The <classname>ExceptionTranslationFilter</classname> caches the original <para> The <classname>ExceptionTranslationFilter</classname> caches the original
request a user makes. When the user authenticates, the request handler makes request a user makes. When the user authenticates, the request handler makes use
use of this cached request to obtain the original URL and redirect to it. of this cached request to obtain the original URL and redirect to it. The
The original request is then rebuilt and used as an alternative. </para> original request is then rebuilt and used as an alternative. </para>
</note> If authentication fails, the configured </note> If authentication fails, the configured
<interfacename>AuthenticationFailureHandler</interfacename> will be invoked. <interfacename>AuthenticationFailureHandler</interfacename> will be invoked. </para>
</para>
</section> </section>
</section> </section>
</chapter> </chapter>

View File

@ -5,9 +5,9 @@
classes, let's take a closer look at one or two of the core interfaces and their classes, let's take a closer look at one or two of the core interfaces and their
implementations, in particular the <interfacename>AuthenticationManager</interfacename>, implementations, in particular the <interfacename>AuthenticationManager</interfacename>,
<interfacename>UserDetailsService</interfacename> and the <interfacename>UserDetailsService</interfacename> and the
<interfacename>AccessDecisionManager</interfacename>. These crop up regularly throughout <interfacename>AccessDecisionManager</interfacename>. These crop up regularly throughout the
the remainder of this document so it's important you know how they are configured and how remainder of this document so it's important you know how they are configured and how they
they operate. </para> operate. </para>
<section xml:id="core-services-authentication-manager"> <section xml:id="core-services-authentication-manager">
<title>The <interfacename>AuthenticationManager</interfacename>, <title>The <interfacename>AuthenticationManager</interfacename>,
<classname>ProviderManager</classname> and <classname>ProviderManager</classname> and
@ -19,27 +19,25 @@
<para>The default implementation in Spring Security is called <para>The default implementation in Spring Security is called
<classname>ProviderManager</classname> and rather than handling the authentication <classname>ProviderManager</classname> and rather than handling the authentication
request itself, it delegates to a list of configured request itself, it delegates to a list of configured
<classname>AuthenticationProvider</classname>s, each of which is queried in turn to <classname>AuthenticationProvider</classname>s, each of which is queried in turn to see
see if it can perform the authentication. Each provider will either throw an exception if it can perform the authentication. Each provider will either throw an exception or
or return a fully populated <interfacename>Authentication</interfacename> object. return a fully populated <interfacename>Authentication</interfacename> object. Remember
Remember our good friends, <interfacename>UserDetails</interfacename> and our good friends, <interfacename>UserDetails</interfacename> and
<interfacename>UserDetailsService</interfacename>? If not, head back to the previous <interfacename>UserDetailsService</interfacename>? If not, head back to the previous
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> (see below). The approach used by the <classname>DaoAuthenticationProvider</classname> (see below). The
loaded <interfacename>UserDetails</interfacename> object - and particularly 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
fully populated <interfacename>Authentication</interfacename> object which is returned populated <interfacename>Authentication</interfacename> object which is returned from a
from a successful authentication and stored in the successful authentication and stored in the <classname>SecurityContext</classname>. </para>
<classname>SecurityContext</classname>. </para> <para> If you are using the namespace, an instance of <classname>ProviderManager</classname>
<para> If you are using the namespace, an instance of is created and maintained internally, and you add providers to it by using the namespace
<classname>ProviderManager</classname> is created and maintained internally, and authentication provider elements (see <link xlink:href="#ns-auth-manager">the namespace
you add providers to it by using the namespace authentication provider elements chapter</link>). In this case, you should not declare a
(see <link xlink:href="#ns-auth-manager">the namespace chapter</link>). In this <classname>ProviderManager</classname> bean in your application context. However, if you
case, you should not declare a <classname>ProviderManager</classname> bean in your are not using the namespace then you would declare it like so: <programlisting language="xml"><![CDATA[
application context. However, if you are not using the namespace then you would declare
it like so: <programlisting language="xml"><![CDATA[
<bean id="authenticationManager" <bean id="authenticationManager"
class="org.springframework.security.authentication.ProviderManager"> class="org.springframework.security.authentication.ProviderManager">
<property name="providers"> <property name="providers">
@ -78,12 +76,12 @@
<para>The simplest <interfacename>AuthenticationProvider</interfacename> implemented by <para>The simplest <interfacename>AuthenticationProvider</interfacename> implemented by
Spring Security is <literal>DaoAuthenticationProvider</literal>, which is also one Spring Security is <literal>DaoAuthenticationProvider</literal>, which is also one
of the earliest supported by the framework. It leverages a of the earliest supported by the framework. It leverages a
<interfacename>UserDetailsService</interfacename> (as a DAO) in order to lookup <interfacename>UserDetailsService</interfacename> (as a DAO) in order to lookup the
the username, password and <interfacename>GrantedAuthority</interfacename>s. It username, password and <interfacename>GrantedAuthority</interfacename>s. It
authenticates the user simply by comparing the password submitted in a authenticates the user simply by comparing the password submitted in a
<classname>UsernamePasswordAuthenticationToken</classname> against the one <classname>UsernamePasswordAuthenticationToken</classname> against the one loaded by
loaded by the <interfacename>UserDetailsService</interfacename>. Configuring the the <interfacename>UserDetailsService</interfacename>. Configuring the provider is
provider is quite simple: <programlisting language="xml"><![CDATA[ quite simple: <programlisting language="xml"><![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="inMemoryDaoImpl"/> <property name="userDetailsService" ref="inMemoryDaoImpl"/>
@ -94,8 +92,8 @@
<interfacename>PasswordEncoder</interfacename> provides encoding and decoding of <interfacename>PasswordEncoder</interfacename> provides encoding and decoding of
passwords presented in the <interfacename>UserDetails</interfacename> object that is passwords presented in the <interfacename>UserDetails</interfacename> object that is
returned from the configured <interfacename>UserDetailsService</interfacename>. A returned from the configured <interfacename>UserDetailsService</interfacename>. A
<interfacename>SaltSource</interfacename> enables the passwords to be populated <interfacename>SaltSource</interfacename> enables the passwords to be populated with
with a "salt", which enhances the security of the passwords in the authentication a "salt", which enhances the security of the passwords in the authentication
repository. These will be discussed in more detail <link repository. These will be discussed in more detail <link
xlink:href="core-services-password-encodin">below</link>. </para> xlink:href="core-services-password-encodin">below</link>. </para>
</section> </section>
@ -104,23 +102,21 @@
<title><interfacename>UserDetailsService</interfacename> Implementations</title> <title><interfacename>UserDetailsService</interfacename> Implementations</title>
<para>As mentioned in the earlier in this reference guide, most authentication providers <para>As mentioned in the earlier in this reference guide, most authentication providers
take advantage of the <interfacename>UserDetails</interfacename> and take advantage of the <interfacename>UserDetails</interfacename> and
<interfacename>UserDetailsService</interfacename> interfaces. Recall that the <interfacename>UserDetailsService</interfacename> interfaces. Recall that the contract
contract for <interfacename>UserDetailsService</interfacename> is a single for <interfacename>UserDetailsService</interfacename> is a single method:</para>
method:</para>
<para> <para>
<programlisting> <programlisting>
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException; UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
</programlisting> </programlisting> </para>
</para>
<para>The returned <interfacename>UserDetails</interfacename> is an interface that provides <para>The returned <interfacename>UserDetails</interfacename> is an interface that provides
getters that guarantee non-null provision of authentication information such as the getters that guarantee non-null provision of authentication information such as the
username, password, granted authorities and whether the user account is enabled or username, password, granted authorities and whether the user account is enabled or
disabled. Most authentication providers will use a disabled. Most authentication providers will use a
<interfacename>UserDetailsService</interfacename>, even if the username and password <interfacename>UserDetailsService</interfacename>, even if the username and password are
are not actually used as part of the authentication decision. They may use the returned not actually used as part of the authentication decision. They may use the returned
<interfacename>UserDetails</interfacename> object just for its <interfacename>UserDetails</interfacename> object just for its
<literal>GrantedAuthority</literal> information, because some other system (like <literal>GrantedAuthority</literal> information, because some other system (like LDAP or
LDAP or X.509 or CAS etc) has undertaken the responsibility of actually validating the X.509 or CAS etc) has undertaken the responsibility of actually validating the
credentials.</para> credentials.</para>
<para>Given <interfacename>UserDetailsService</interfacename> is so simple to implement, it <para>Given <interfacename>UserDetailsService</interfacename> is so simple to implement, it
should be easy for users to retrieve authentication information using a persistence should be easy for users to retrieve authentication information using a persistence
@ -133,8 +129,8 @@
many applications do not require such complexity. This is particularly true if many applications do not require such complexity. This is particularly true if
you're building a prototype application or just starting integrating Spring you're building a prototype application or just starting integrating Spring
Security, when you don't really want to spend time configuring databases or writing Security, when you don't really want to spend time configuring databases or writing
<interfacename>UserDetailsService</interfacename> implementations. For this sort <interfacename>UserDetailsService</interfacename> implementations. For this sort of
of situation, a simple option is to use the <literal>user-service</literal> element situation, a simple option is to use the <literal>user-service</literal> element
from the security <link xlink:href="#ns-minimal">namespace</link>: <programlisting><![CDATA[ from the security <link xlink:href="#ns-minimal">namespace</link>: <programlisting><![CDATA[
<user-service id="userDetailsService"> <user-service id="userDetailsService">
<user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" /> <user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
@ -158,11 +154,10 @@
Spring JDBC is used, so it avoids the complexity of a fully-featured object Spring JDBC is used, so it avoids the complexity of a fully-featured object
relational mapper (ORM) just to store user details. If your application does use an relational mapper (ORM) just to store user details. If your application does use an
ORM tool, you might prefer to write a custom ORM tool, you might prefer to write a custom
<interfacename>UserDetailsService</interfacename> to reuse the mapping files <interfacename>UserDetailsService</interfacename> to reuse the mapping files you've
you've probably already created. Returning to <literal>JdbcDaoImpl</literal>, an probably already created. Returning to <literal>JdbcDaoImpl</literal>, an example
example configuration is shown below:</para> configuration is shown below:</para>
<para> <para> <programlisting language="xml"><![CDATA[
<programlisting language="xml"><![CDATA[
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/> <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/> <property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/>
@ -173,19 +168,17 @@
<bean id="userDetailsService" <bean id="userDetailsService"
class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl"> class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
<property name="dataSource" ref="dataSource"/> <property name="dataSource" ref="dataSource"/>
</bean> ]]> </programlisting> </bean> ]]> </programlisting> </para>
</para>
<para>You can use different relational database management systems by modifying the <para>You can use different relational database management systems by modifying the
<literal>DriverManagerDataSource</literal> shown above. You can also use a <literal>DriverManagerDataSource</literal> shown above. You can also use a global
global data source obtained from JNDI, as with any other Spring data source obtained from JNDI, as with any other Spring configuration.</para>
configuration.</para>
<section> <section>
<title>Authority Groups</title> <title>Authority Groups</title>
<para>By default, <classname>JdbcDaoImpl</classname> loads the authorities for a <para>By default, <classname>JdbcDaoImpl</classname> loads the authorities for a
single user with the assumption that the authorities are mapped directly to single user with the assumption that the authorities are mapped directly to
users (see the <link xlink:href="#appendix-schema">database schema users (see the <link xlink:href="#appendix-schema">database schema
appendix</link>). An alternative approach is to partition the authorities appendix</link>). An alternative approach is to partition the authorities into
into groups and assign groups to the user. Some people prefer this approach as a groups and assign groups to the user. Some people prefer this approach as a
means of administering user rights. See the <classname>JdbcDaoImpl</classname> means of administering user rights. See the <classname>JdbcDaoImpl</classname>
Javadoc for more information on how to enable the use of group authorities. The Javadoc for more information on how to enable the use of group authorities. The
group schema is also included in the appendix.</para> group schema is also included in the appendix.</para>
@ -231,14 +224,14 @@
<para> One potential problem with the use of password hashes that it is relatively easy <para> One potential problem with the use of password hashes that it is relatively easy
to get round the one-way property of the hash if a common word is used for the to get round the one-way property of the hash if a common word is used for the
input. For example, if you search for the hash value input. For example, if you search for the hash value
<literal>5f4dcc3b5aa765d61d8327deb882cf99</literal> using google, you will <literal>5f4dcc3b5aa765d61d8327deb882cf99</literal> using google, you will quickly
quickly find the original word <quote>password</quote>. In a similar way, an find the original word <quote>password</quote>. In a similar way, an attacker can
attacker can build a dictionary of hashes from a standard word list and use this to build a dictionary of hashes from a standard word list and use this to lookup the
lookup the original password. One way to help prevent this is to have a suitably original password. One way to help prevent this is to have a suitably strong
strong password policy to try to prevent common words from being used. Another is to password policy to try to prevent common words from being used. Another is to use a
use a <quote>salt</quote> when calculating the hashes. This is an additional string <quote>salt</quote> when calculating the hashes. This is an additional string of
of known data for each user which is combined with the password before calculating known data for each user which is combined with the password before calculating the
the hash. Ideally the data should be as random as possible, but in practice any salt hash. Ideally the data should be as random as possible, but in practice any salt
value is usually preferable to none. Spring Security has a value is usually preferable to none. Spring Security has a
<interfacename>SaltSource</interfacename> interface which can be used by an <interfacename>SaltSource</interfacename> interface which can be used by an
authentication provider to generate a salt value for a particular user. Using a salt authentication provider to generate a salt value for a particular user. Using a salt
@ -248,31 +241,31 @@
<section> <section>
<title> Hashing and Authentication</title> <title> Hashing and Authentication</title>
<para>When an authentication provider (such as Spring Security's <para>When an authentication provider (such as Spring Security's
<classname>DaoAuthenticationProvider</classname> needs to check the password in <classname>DaoAuthenticationProvider</classname> needs to check the password in a
a submitted authentication request against the known value for a user, and the submitted authentication request against the known value for a user, and the stored
stored password is encoded in some way, then the submitted value must be encoded password is encoded in some way, then the submitted value must be encoded using
using exactly the same algorithm. It's up to you to check that these are compatible exactly the same algorithm. It's up to you to check that these are compatible as
as Spring Security has no control over the persistent values. If you add password Spring Security has no control over the persistent values. If you add password
hashing to your authentication configuration in Spring Security, and your database hashing to your authentication configuration in Spring Security, and your database
contains plaintext passwords, then there is no way authentication can succeed. Even contains plaintext passwords, then there is no way authentication can succeed. Even
if you are aware that your database is using MD5 to encode the passwords, for if you are aware that your database is using MD5 to encode the passwords, for
example, and your application is configured to use Spring Security's example, and your application is configured to use Spring Security's
<classname>Md5PasswordEncoder</classname>, there are still things that can go <classname>Md5PasswordEncoder</classname>, there are still things that can go wrong.
wrong. The database may have the passwords encoded in Base 64, for example while the The database may have the passwords encoded in Base 64, for example while the
enocoder is using hexadecimal strings (the default)<footnote><para>You can configure enocoder is using hexadecimal strings (the default)<footnote>
the encoder to use Base 64 instead of hex by setting the <para>You can configure the encoder to use Base 64 instead of hex by setting the
<literal>encodeHashAsBase64</literal> property to <literal>encodeHashAsBase64</literal> property to <literal>true</literal>. Check
<literal>true</literal>. Check the Javadoc for the Javadoc for <classname>MessageDigestPasswordEncoder</classname> and its
<classname>MessageDigestPasswordEncoder</classname> and its parent parent classes for more information.</para>
classes for more information.</para></footnote>. Alternatively your database </footnote>. Alternatively your database may be using upper-case while the output
may be using upper-case while the output from the encoder is lower-case. Make sure from the encoder is lower-case. Make sure you write a test to check the output from
you write a test to check the output from your configured password encoder with a your configured password encoder with a known password and salt combination and
known password and salt combination and check that it matches the database value check that it matches the database value before going further and attempting to
before going further and attempting to authenticate through your application. For authenticate through your application. For more information on the default method
more information on the default method for merging salt and password, see the for merging salt and password, see the Javadoc for
Javadoc for <classname>BasePasswordEncoder</classname>. If you want to generate <classname>BasePasswordEncoder</classname>. If you want to generate encoded
encoded passwords directly in Java for storage in your user database, then you can passwords directly in Java for storage in your user database, then you can use the
use the <methodname>encodePassword</methodname> method on the <methodname>encodePassword</methodname> method on the
<interfacename>PasswordEncoder</interfacename>.</para> <interfacename>PasswordEncoder</interfacename>.</para>
</section> </section>
</section> </section>

View File

@ -8,8 +8,8 @@
</info> </info>
<para>Spring Security includes a production-quality <para>Spring Security includes a production-quality
<classname>AuthenticationProvider</classname> implementation called <classname>AuthenticationProvider</classname> implementation called
<literal>DaoAuthenticationProvider</literal>. This authentication provider is <literal>DaoAuthenticationProvider</literal>. This authentication provider is compatible
compatible with all of the authentication mechanisms that generate a with all of the authentication mechanisms that generate a
<literal>UsernamePasswordAuthenticationToken</literal>, and is probably the most <literal>UsernamePasswordAuthenticationToken</literal>, and is probably the most
commonly used provider in the framework. Like most of the other authentication commonly used provider in the framework. Like most of the other authentication
providers, the DaoAuthenticationProvider leverages a UserDetailsService in order to providers, the DaoAuthenticationProvider leverages a UserDetailsService in order to
@ -27,8 +27,7 @@
at the start of this part of the reference guide), and ensuring a suitable at the start of this part of the reference guide), and ensuring a suitable
authentication mechanism is configured to present a UsernamePasswordAuthenticationToken, authentication mechanism is configured to present a UsernamePasswordAuthenticationToken,
the configuration of the provider itself is rather simple:</para> the configuration of the provider itself is rather simple:</para>
<para> <para> <programlisting>
<programlisting>
<![CDATA[ <![CDATA[
<bean id="daoAuthenticationProvider" <bean id="daoAuthenticationProvider"
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider"> class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
@ -36,14 +35,13 @@
<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> </programlisting> </para>
</para>
<para>The <literal>PasswordEncoder</literal> and <literal>SaltSource</literal> are optional. <para>The <literal>PasswordEncoder</literal> and <literal>SaltSource</literal> are optional.
A <literal>PasswordEncoder</literal> provides encoding and decoding of passwords A <literal>PasswordEncoder</literal> provides encoding and decoding of passwords
presented in the <interfacename>UserDetails</interfacename> object that is returned from presented in the <interfacename>UserDetails</interfacename> object that is returned from
the configured <interfacename>UserDetailsService</interfacename>. A the configured <interfacename>UserDetailsService</interfacename>. A
<literal>SaltSource</literal> enables the passwords to be populated with a "salt", <literal>SaltSource</literal> enables the passwords to be populated with a "salt", which
which enhances the security of the passwords in the authentication repository. enhances the security of the passwords in the authentication repository.
<literal>PasswordEncoder</literal> implementations are provided with Spring Security <literal>PasswordEncoder</literal> implementations are provided with Spring Security
covering MD5, SHA and cleartext encodings. Two <literal>SaltSource</literal> covering MD5, SHA and cleartext encodings. Two <literal>SaltSource</literal>
implementations are also provided: <literal>SystemWideSaltSource</literal> which encodes implementations are also provided: <literal>SystemWideSaltSource</literal> which encodes
@ -55,14 +53,12 @@
supports optional caching of <interfacename>UserDetails</interfacename> objects. The supports optional caching of <interfacename>UserDetails</interfacename> objects. The
<literal>UserCache</literal> interface enables the <literal>UserCache</literal> interface enables the
<literal>DaoAuthenticationProvider</literal> to place a <literal>DaoAuthenticationProvider</literal> to place a
<interfacename>UserDetails</interfacename> object into the cache, and retrieve it <interfacename>UserDetails</interfacename> object into the cache, and retrieve it from
from the cache upon subsequent authentication attempts for the same username. By default the cache upon subsequent authentication attempts for the same username. By default the
the <literal>DaoAuthenticationProvider</literal> uses the <literal>DaoAuthenticationProvider</literal> uses the <literal>NullUserCache</literal>,
<literal>NullUserCache</literal>, which performs no caching. A usable caching which performs no caching. A usable caching implementation is also provided,
implementation is also provided, <literal>EhCacheBasedUserCache</literal>, which is <literal>EhCacheBasedUserCache</literal>, which is configured as follows:</para>
configured as follows:</para> <para> <programlisting><![CDATA[
<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"/>
@ -82,15 +78,14 @@
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> </programlisting> </para>
</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>
<literal>Cache</literal> object. The <literal>Cache</literal> object can be obtained object. The <literal>Cache</literal> object can be obtained from wherever you like,
from wherever you like, although we recommend you use Spring's factory classes as shown although we recommend you use Spring's factory classes as shown in the above
in the above configuration. If using Spring's factory classes, please refer to the configuration. If using Spring's factory classes, please refer to the Spring
Spring documentation for further details on how to optimise the cache storage location, documentation for 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 application, <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 you don't need to use a cache as the user's authentication information will be

View File

@ -9,9 +9,9 @@
<para>Complex applications often will find the need to define access permissions not simply <para>Complex applications often will find the need to define access permissions not simply
at a web request or method invocation level. Instead, security decisions need to at a web request or method invocation level. Instead, security decisions need to
comprise both who (<interfacename>Authentication</interfacename>), where comprise both who (<interfacename>Authentication</interfacename>), where
(<classname>MethodInvocation</classname>) and what (<literal>SomeDomainObject</literal>). In (<classname>MethodInvocation</classname>) and what
other words, authorization decisions also need to consider the actual domain object (<literal>SomeDomainObject</literal>). In other words, authorization decisions also need
instance subject of a method invocation.</para> to consider the actual domain object instance subject of a method invocation.</para>
<para>Imagine you're designing an application for a pet clinic. There will be two main <para>Imagine you're designing an application for a pet clinic. There will be two main
groups of users of your Spring-based application: staff of the pet clinic, as well as groups of users of your Spring-based application: staff of the pet clinic, as well as
the pet clinic's customers. The staff will have access to all of the data, whilst your the pet clinic's customers. The staff will have access to all of the data, whilst your
@ -29,42 +29,42 @@
object.</para> object.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>Write an <interfacename>AccessDecisionVoter</interfacename> to enforce the security <para>Write an <interfacename>AccessDecisionVoter</interfacename> to enforce the
from the <literal>GrantedAuthority[]</literal>s stored in the security from the <literal>GrantedAuthority[]</literal>s stored in the
<interfacename>Authentication</interfacename> object. This would mean your <interfacename>Authentication</interfacename> object. This would mean your
<interfacename>AuthenticationManager</interfacename> would need to populate the <interfacename>AuthenticationManager</interfacename> would need to populate the
<interfacename>Authentication</interfacename> with custom <interfacename>Authentication</interfacename> with custom
<interfacename>GrantedAuthority</interfacename>[]s representing each of the <interfacename>GrantedAuthority</interfacename>[]s representing each of the
<literal>Customer</literal> domain object instances the principal has <literal>Customer</literal> domain object instances the principal has access
access to.</para> to.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>Write an <interfacename>AccessDecisionVoter</interfacename> to enforce the security <para>Write an <interfacename>AccessDecisionVoter</interfacename> to enforce the
and open the target <literal>Customer</literal> domain object directly. This security and open the target <literal>Customer</literal> domain object directly.
would mean your voter needs access to a DAO that allows it to retrieve the This would mean your voter needs access to a DAO that allows it to retrieve the
<literal>Customer</literal> object. It would then access the <literal>Customer</literal> object. It would then access the
<literal>Customer</literal> object's collection of approved users and <literal>Customer</literal> object's collection of approved users and make the
make the appropriate decision.</para> appropriate decision.</para>
</listitem> </listitem>
</orderedlist></para> </orderedlist></para>
<para>Each one of these approaches is perfectly legitimate. However, the first couples your <para>Each one of these approaches is perfectly legitimate. However, the first couples your
authorization checking to your business code. The main problems with this include the authorization checking to your business code. The main problems with this include the
enhanced difficulty of unit testing and the fact it would be more difficult to reuse the enhanced difficulty of unit testing and the fact it would be more difficult to reuse the
<literal>Customer</literal> authorization logic elsewhere. Obtaining the <literal>Customer</literal> authorization logic elsewhere. Obtaining the
<literal>GrantedAuthority[]</literal>s from the <interfacename>Authentication</interfacename> <literal>GrantedAuthority[]</literal>s from the
object is also fine, but will not scale to large numbers of <interfacename>Authentication</interfacename> object is also fine, but will not scale to
<literal>Customer</literal>s. If a user might be able to access 5,000 large numbers of <literal>Customer</literal>s. If a user might be able to access 5,000
<literal>Customer</literal>s (unlikely in this case, but imagine if it were a popular <literal>Customer</literal>s (unlikely in this case, but imagine if it were a popular
vet for a large Pony Club!) the amount of memory consumed and time required to construct vet for a large Pony Club!) the amount of memory consumed and time required to construct
the <interfacename>Authentication</interfacename> object would be undesirable. The final method, the <interfacename>Authentication</interfacename> object would be undesirable. The final
opening the <literal>Customer</literal> directly from external code, is probably the method, opening the <literal>Customer</literal> directly from external code, is probably
best of the three. It achieves separation of concerns, and doesn't misuse memory or CPU the best of the three. It achieves separation of concerns, and doesn't misuse memory or
cycles, but it is still inefficient in that both the CPU cycles, but it is still inefficient in that both the
<interfacename>AccessDecisionVoter</interfacename> and the eventual business method itself will <interfacename>AccessDecisionVoter</interfacename> and the eventual business method
perform a call to the DAO responsible for retrieving the <literal>Customer</literal> itself will perform a call to the DAO responsible for retrieving the
object. Two accesses per method invocation is clearly undesirable. In addition, with <literal>Customer</literal> object. Two accesses per method invocation is clearly
every approach listed you'll need to write your own access control list (ACL) undesirable. In addition, with every approach listed you'll need to write your own
persistence and business logic from scratch.</para> access control list (ACL) persistence and business logic from scratch.</para>
<para>Fortunately, there is another alternative, which we'll talk about below.</para> <para>Fortunately, there is another alternative, which we'll talk about below.</para>
</section> </section>
<section xml:id="domain-acls-key-concepts"> <section xml:id="domain-acls-key-concepts">
@ -83,12 +83,12 @@
(and modifying those ACLs)</para> (and modifying those ACLs)</para>
</listitem> </listitem>
<listitem> <listitem>
<para>A way of ensuring a given principal is permitted to work with your <para>A way of ensuring a given principal is permitted to work with your objects,
objects, before methods are called</para> before methods are called</para>
</listitem> </listitem>
<listitem> <listitem>
<para>A way of ensuring a given principal is permitted to work with your objects <para>A way of ensuring a given principal is permitted to work with your objects (or
(or something they return), after methods are called</para> something they return), after methods are called</para>
</listitem> </listitem>
</itemizedlist></para> </itemizedlist></para>
<para>As indicated by the first bullet point, one of the main capabilities of the Spring <para>As indicated by the first bullet point, one of the main capabilities of the Spring
@ -105,43 +105,40 @@
main tables used by default in the implementation. The tables are presented below in main tables used by default in the implementation. The tables are presented below in
order of size in a typical Spring Security ACL deployment, with the table with the most order of size in a typical Spring Security ACL deployment, with the table with the most
rows listed last:</para> rows listed last:</para>
<para> <para> <itemizedlist>
<itemizedlist>
<listitem> <listitem>
<para>ACL_SID allows us to uniquely identify any principal or authority in the <para>ACL_SID allows us to uniquely identify any principal or authority in the
system ("SID" stands for "security identity"). The only columns are the ID, system ("SID" stands for "security identity"). The only columns are the ID, a
a textual representation of the SID, and a flag to indicate whether the textual representation of the SID, and a flag to indicate whether the textual
textual representation refers to a principal name or a representation refers to a principal name or a
<interfacename>GrantedAuthority</interfacename>. Thus, there is a single row for <interfacename>GrantedAuthority</interfacename>. Thus, there is a single row for
each unique principal or <interfacename>GrantedAuthority</interfacename>. When used in each unique principal or <interfacename>GrantedAuthority</interfacename>. When
the context of receiving a permission, a SID is generally called a used in the context of receiving a permission, a SID is generally called a
"recipient".</para> "recipient".</para>
</listitem> </listitem>
<listitem> <listitem>
<para>ACL_CLASS allows us to uniquely identify any domain object class in the <para>ACL_CLASS allows us to uniquely identify any domain object class in the
system. The only columns are the ID and the Java class name. Thus, there is system. The only columns are the ID and the Java class name. Thus, there is a
a single row for each unique Class we wish to store ACL permissions single row for each unique Class we wish to store ACL permissions for.</para>
for.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>ACL_OBJECT_IDENTITY stores information for each unique domain object <para>ACL_OBJECT_IDENTITY stores information for each unique domain object instance
instance in the system. Columns include the ID, a foreign key to the in the system. Columns include the ID, a foreign key to the ACL_CLASS table, a
ACL_CLASS table, a unique identifier so we know which ACL_CLASS instance unique identifier so we know which ACL_CLASS instance we're providing
we're providing information for, the parent, a foreign key to the ACL_SID information for, the parent, a foreign key to the ACL_SID table to represent the
table to represent the owner of the domain object instance, and whether we owner of the domain object instance, and whether we allow ACL entries to inherit
allow ACL entries to inherit from any parent ACL. We have a single row for from any parent ACL. We have a single row for every domain object instance we're
every domain object instance we're storing ACL permissions for.</para> storing ACL permissions for.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>Finally, ACL_ENTRY stores the individual permissions assigned to each <para>Finally, ACL_ENTRY stores the individual permissions assigned to each
recipient. Columns include a foreign key to the ACL_OBJECT_IDENTITY, the recipient. Columns include a foreign key to the ACL_OBJECT_IDENTITY, the
recipient (ie a foreign key to ACL_SID), whether we'll be auditing or not, recipient (ie a foreign key to ACL_SID), whether we'll be auditing or not, and
and the integer bit mask that represents the actual permission being granted the integer bit mask that represents the actual permission being granted or
or denied. We have a single row for every recipient that receives a denied. We have a single row for every recipient that receives a permission to
permission to work with a domain object.</para> work with a domain object.</para>
</listitem> </listitem>
</itemizedlist> </itemizedlist> </para>
</para>
<para>As mentioned in the last paragraph, the ACL system uses integer bit masking. Don't <para>As mentioned in the last paragraph, the ACL system uses integer bit masking. Don't
worry, you need not be aware of the finer points of bit shifting to use the ACL system, worry, you need not be aware of the finer points of bit shifting to use the ACL system,
but suffice to say that we have 32 bits we can switch on or off. Each of these bits but suffice to say that we have 32 bits we can switch on or off. Each of these bits
@ -163,9 +160,9 @@
<para><literal>Acl</literal>: Every domain object has one and only one <para><literal>Acl</literal>: Every domain object has one and only one
<literal>Acl</literal> object, which internally holds the <literal>Acl</literal> object, which internally holds the
<literal>AccessControlEntry</literal>s as well as knows the owner of the <literal>AccessControlEntry</literal>s as well as knows the owner of the
<literal>Acl</literal>. An Acl does not refer directly to the domain object, <literal>Acl</literal>. An Acl does not refer directly to the domain object, but
but instead to an <literal>ObjectIdentity</literal>. The <literal>Acl</literal> instead to an <literal>ObjectIdentity</literal>. The <literal>Acl</literal> is
is stored in the ACL_OBJECT_IDENTITY table.</para> stored in the ACL_OBJECT_IDENTITY table.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><literal>AccessControlEntry</literal>: An <literal>Acl</literal> holds <para><literal>AccessControlEntry</literal>: An <literal>Acl</literal> holds
@ -183,11 +180,11 @@
</listitem> </listitem>
<listitem> <listitem>
<para><literal>Sid</literal>: The ACL module needs to refer to principals and <para><literal>Sid</literal>: The ACL module needs to refer to principals and
<literal>GrantedAuthority[]</literal>s. A level of indirection is provided <literal>GrantedAuthority[]</literal>s. A level of indirection is provided by
by the <literal>Sid</literal> interface, which is an abbreviation of "security the <literal>Sid</literal> interface, which is an abbreviation of "security
identity". Common classes include <literal>PrincipalSid</literal> (to represent identity". Common classes include <literal>PrincipalSid</literal> (to represent
the principal inside an <interfacename>Authentication</interfacename> object) and the principal inside an <interfacename>Authentication</interfacename> object)
<literal>GrantedAuthoritySid</literal>. The security identity information is and <literal>GrantedAuthoritySid</literal>. The security identity information is
stored in the ACL_SID table.</para> stored in the ACL_SID table.</para>
</listitem> </listitem>
<listitem> <listitem>
@ -227,15 +224,14 @@
ACL information somewhere. This necessitates the instantiation of a ACL information somewhere. This necessitates the instantiation of a
<literal>DataSource</literal> using Spring. The <literal>DataSource</literal> is then <literal>DataSource</literal> using Spring. The <literal>DataSource</literal> is then
injected into a <literal>JdbcMutableAclService</literal> and injected into a <literal>JdbcMutableAclService</literal> and
<literal>BasicLookupStrategy</literal> instance. The latter provides <literal>BasicLookupStrategy</literal> instance. The latter provides high-performance
high-performance ACL retrieval capabilities, and the former provides mutator ACL retrieval capabilities, and the former provides mutator capabilities. Refer to one
capabilities. Refer to one of the samples that ship with Spring Security for an example of the samples that ship with Spring Security for an example configuration. You'll also
configuration. You'll also need to populate the database with the four ACL-specific need to populate the database with the four ACL-specific tables listed in the last
tables listed in the last section (refer to the ACL samples for the appropriate SQL section (refer to the ACL samples for the appropriate SQL statements).</para>
statements).</para>
<para>Once you've created the required schema and instantiated <para>Once you've created the required schema and instantiated
<literal>JdbcMutableAclService</literal>, you'll next need to ensure your domain <literal>JdbcMutableAclService</literal>, you'll next need to ensure your domain model
model supports interoperability with the Spring Security ACL package. Hopefully supports interoperability with the Spring Security ACL package. Hopefully
<literal>ObjectIdentityImpl</literal> will prove sufficient, as it provides a large <literal>ObjectIdentityImpl</literal> will prove sufficient, as it provides a large
number of ways in which it can be used. Most people will have domain objects that number of ways in which it can be used. Most people will have domain objects that
contain a <literal>public Serializable getId()</literal> method. If the return type is contain a <literal>public Serializable getId()</literal> method. If the return type is
@ -272,7 +268,8 @@ aclService.updateAcl(acl);
position in the Acl the new entry will be inserted. In the example above, we're just position in the Acl the new entry will be inserted. In the example above, we're just
putting the new ACE at the end of the existing ACEs. The final argument is a boolean putting the new ACE at the end of the existing ACEs. The final argument is a boolean
indicating whether the ACE is granting or denying. Most of the time it will be granting indicating whether the ACE is granting or denying. Most of the time it will be granting
(true), but if it is denying (false), the permissions are effectively being blocked.</para> (true), but if it is denying (false), the permissions are effectively being
blocked.</para>
<para>Spring Security does not provide any special integration to automatically create, <para>Spring Security does not provide any special integration to automatically create,
update or delete ACLs as part of your DAO or repository operations. Instead, you will update or delete ACLs as part of your DAO or repository operations. Instead, you will
need to write code like shown above for your individual domain objects. It's worth need to write code like shown above for your individual domain objects. It's worth
@ -282,15 +279,15 @@ aclService.updateAcl(acl);
<para>Once you've used the above techniques to store some ACL information in the database, <para>Once you've used the above techniques to store some ACL information in the database,
the next step is to actually use the ACL information as part of authorization decision the next step is to actually use the ACL information as part of authorization decision
logic. You have a number of choices here. You could write your own logic. You have a number of choices here. You could write your own
<interfacename>AccessDecisionVoter</interfacename> or <literal>AfterInvocationProvider</literal> <interfacename>AccessDecisionVoter</interfacename> or
that respectively fires before or after a method invocation. Such classes would use <literal>AfterInvocationProvider</literal> that respectively fires before or after a
<literal>AclService</literal> to retrieve the relevant ACL and then call method invocation. Such classes would use <literal>AclService</literal> to retrieve the
<literal>Acl.isGranted(Permission[] permission, Sid[] sids, boolean relevant ACL and then call <literal>Acl.isGranted(Permission[] permission, Sid[] sids,
administrativeMode)</literal> to decide whether permission is granted or denied. boolean administrativeMode)</literal> to decide whether permission is granted or denied.
Alternately, you could use our <literal>AclEntryVoter</literal>, Alternately, you could use our <literal>AclEntryVoter</literal>,
<literal>AclEntryAfterInvocationProvider</literal> or <literal>AclEntryAfterInvocationProvider</literal> or
<literal>AclEntryAfterInvocationCollectionFilteringProvider</literal> classes. All <literal>AclEntryAfterInvocationCollectionFilteringProvider</literal> classes. All of
of these classes provide a declarative-based approach to evaluating ACL information at these classes provide a declarative-based approach to evaluating ACL information at
runtime, freeing you from needing to write any code. Please refer to the sample runtime, freeing you from needing to write any code. Please refer to the sample
applications to learn how to use these classes.</para> applications to learn how to use these classes.</para>
</section> </section>

View File

@ -18,8 +18,8 @@
<section xml:id="el-common-built-in"> <section xml:id="el-common-built-in">
<title>Common Built-In Expressions</title> <title>Common Built-In Expressions</title>
<para>The base class for expression root objects is <para>The base class for expression root objects is
<classname>SecurityExpressionRoot</classname>. This provides some common <classname>SecurityExpressionRoot</classname>. This provides some common expressions
expressions which are available in both web and method security.</para> which are available in both web and method security.</para>
<table frame="none"> <table frame="none">
<title>Common built-in expressions</title> <title>Common built-in expressions</title>
<tgroup cols="2"> <tgroup cols="2">
@ -51,8 +51,8 @@
<row> <row>
<entry><literal>authentication</literal></entry> <entry><literal>authentication</literal></entry>
<entry>Allows direct access to the current <entry>Allows direct access to the current
<interfacename>Authentication</interfacename> object obtained <interfacename>Authentication</interfacename> object obtained from
from the <interfacename>SecurityContext</interfacename></entry> the <interfacename>SecurityContext</interfacename></entry>
</row> </row>
<row> <row>
<entry><literal>permitAll</literal></entry> <entry><literal>permitAll</literal></entry>
@ -90,8 +90,8 @@
<section xml:id="el-access-web"> <section xml:id="el-access-web">
<title>Web Security Expressions</title> <title>Web Security Expressions</title>
<para> To use expressions to secure individual URLs, you would first need to set the <para> To use expressions to secure individual URLs, you would first need to set the
<literal>use-expressions</literal> attribute in the <literal>&lt;http></literal> <literal>use-expressions</literal> attribute in the <literal>&lt;http></literal> element
element to <literal>true</literal>. Spring Security will then expect the to <literal>true</literal>. Spring Security will then expect the
<literal>access</literal> attributes of the <literal>&lt;intercept-url></literal> <literal>access</literal> attributes of the <literal>&lt;intercept-url></literal>
elements to contain Spring EL expressions. The expressions should evaluate to a boolean, elements to contain Spring EL expressions. The expressions should evaluate to a boolean,
defining whether access should be allowed or not. For example:<programlisting><![CDATA[ defining whether access should be allowed or not. For example:<programlisting><![CDATA[
@ -106,8 +106,8 @@
already seen the built-in <literal>hasRole</literal> expression in the previous section. already seen the built-in <literal>hasRole</literal> expression in the previous section.
The expression <literal>hasIpAddress</literal> is an additional built-in expression The expression <literal>hasIpAddress</literal> is an additional built-in expression
which is specific to web security. It is defined by the which is specific to web security. It is defined by the
<classname>WebSecurityExpressionRoot</classname> class, an instance of which is used <classname>WebSecurityExpressionRoot</classname> class, an instance of which is used as
as the expression root object when evaluation web-access expressions. This object also the expression root object when evaluation web-access expressions. This object also
directly exposed the <interfacename>HttpServletRequest</interfacename> object under the directly exposed the <interfacename>HttpServletRequest</interfacename> object under the
name <literal>request</literal> so you can invoke the request directly in an name <literal>request</literal> so you can invoke the request directly in an
expression.</para> expression.</para>
@ -150,25 +150,25 @@
whether the current user has the <quote>admin</quote>permission for the given whether the current user has the <quote>admin</quote>permission for the given
contact. The built-in <literal>hasPermission()</literal> expression is linked contact. The built-in <literal>hasPermission()</literal> expression is linked
into the Spring Security ACL module through the application context, as we'll into the Spring Security ACL module through the application context, as we'll
<link xlink:href="#el-permission-evaluator">see below</link>. You can access <link xlink:href="#el-permission-evaluator">see below</link>. You can access any
any of the method arguments by name as expression variables, provided your code of the method arguments by name as expression variables, provided your code has
has debug information compiled in. Any Spring-EL functionality is available debug information compiled in. Any Spring-EL functionality is available within
within the expression, so you can also access properties on the arguments. For the expression, so you can also access properties on the arguments. For example,
example, if you wanted a particular method to only allow access to a user whose if you wanted a particular method to only allow access to a user whose username
username matched that of the contact, you could write</para> matched that of the contact, you could write</para>
<programlisting> <programlisting>
@PreAuthorize("#contact.name == principal.name)") @PreAuthorize("#contact.name == principal.name)")
public void doSomething(Contact contact);</programlisting> public void doSomething(Contact contact);</programlisting>
<para>Here we are accessing another builtin expression, which is the <para>Here we are accessing another builtin expression, which is the
<literal>principal</literal> of the current Spring Security <literal>principal</literal> of the current Spring Security
<interfacename>Authentication</interfacename> object obtained from the <interfacename>Authentication</interfacename> object obtained from the security
security context. You can also access the context. You can also access the <interfacename>Authentication</interfacename>
<interfacename>Authentication</interfacename> object itself directly using object itself directly using the expression name
the expression name <literal>authentication</literal>.</para> <literal>authentication</literal>.</para>
<para>Less commonly, you may wish to perform an access-control check after the <para>Less commonly, you may wish to perform an access-control check after the
method has been invoked. This can be achieved using the method has been invoked. This can be achieved using the
<literal>@PostAuthorize</literal> annotation. To access the return value <literal>@PostAuthorize</literal> annotation. To access the return value from a
from a method, use the builtin name <literal>returnObject</literal> in the method, use the builtin name <literal>returnObject</literal> in the
expression.</para> expression.</para>
</section> </section>
<section> <section>
@ -227,8 +227,7 @@
long as it is consistent with how the permissions are loaded.</para> long as it is consistent with how the permissions are loaded.</para>
<para>To use <literal>hasPermission()</literal> expressions, you have to explicitly <para>To use <literal>hasPermission()</literal> expressions, you have to explicitly
configure a <interfacename>PermissionEvaluator</interfacename> in your configure a <interfacename>PermissionEvaluator</interfacename> in your
application context. This would look something like this: application context. This would look something like this: <programlisting language="xml"> <![CDATA[
<programlisting language="xml"> <![CDATA[
<security:global-method-security pre-post-annotations="enabled"> <security:global-method-security pre-post-annotations="enabled">
<security:expression-handler ref="expressionHandler"/> <security:expression-handler ref="expressionHandler"/>
</security:global-method-security> </security:global-method-security>
@ -239,9 +238,8 @@
</bean>]]></programlisting>Where <literal>myPermissionEvaluator</literal> is the bean which </bean>]]></programlisting>Where <literal>myPermissionEvaluator</literal> is the bean which
implements <interfacename>PermissionEvaluator</interfacename>. Usually this will implements <interfacename>PermissionEvaluator</interfacename>. Usually this will
be the implementation from the ACL module which is called be the implementation from the ACL module which is called
<classname>AclPermissionEvaluator</classname>. See the <classname>AclPermissionEvaluator</classname>. See the <quote>Contacts</quote>
<quote>Contacts</quote> sample application configuration for more sample application configuration for more details.</para>
details.</para>
</section> </section>
</section> </section>
</section> </section>

View File

@ -1,67 +1,68 @@
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="form"> <chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="form">
<info><title>Form Authentication Mechanism</title></info> <info>
<title>Form Authentication Mechanism</title>
</info>
<section xml:id="form-overview"> <section xml:id="form-overview">
<info><title>Overview</title></info> <info>
<title>Overview</title>
</info>
<para>HTTP Form Authentication involves using the <para>HTTP Form Authentication involves using the
<literal>UsernamePasswordAuthenticationFilter</literal> to process a login <literal>UsernamePasswordAuthenticationFilter</literal> to process a login form. This is
form. This is the most common way for an application to authenticate end the most common way for an application to authenticate end users. Form-based
users. Form-based authentication is entirely compatible with the DAO, LDAP authentication is entirely compatible with the DAO, LDAP and JAAS authentication
and JAAS authentication providers.</para> providers.</para>
<para>This is also the mechanism used by the &lt;form-login&gt; element from the namespace <para>This is also the mechanism used by the &lt;form-login&gt; element from the namespace
and it's recommended that you use that unless you have specific customization requirements. and it's recommended that you use that unless you have specific customization
</para> requirements. </para>
</section> </section>
<section xml:id="form-config"> <section xml:id="form-config">
<info><title>Configuration</title></info> <info>
<title>Configuration</title>
</info>
<para>The login form simply contains <literal>j_username</literal> and <para>The login form simply contains <literal>j_username</literal> and
<literal>j_password</literal> input fields, and posts to a URL that is <literal>j_password</literal> input fields, and posts to a URL that is monitored by the
monitored by the filter (by default filter (by default <literal>/j_spring_security_check</literal>). You should add an
<literal>/j_spring_security_check</literal>). You should add an <literal>UsernamePasswordAuthenticationFilter</literal> to your application context: <programlisting><![CDATA[
<literal>UsernamePasswordAuthenticationFilter</literal> to your application context:
<programlisting><![CDATA[
<bean id="authenticationProcessingFilter" class= <bean id="authenticationProcessingFilter" class=
"org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"> "org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/> <property name="authenticationManager" ref="authenticationManager"/>
<property name="filterProcessesUrl" value="/j_spring_security_check"/> <property name="filterProcessesUrl" value="/j_spring_security_check"/>
</bean> ]]> </bean> ]]>
</programlisting></para> </programlisting></para>
<para> <para> The configured <interfacename>AuthenticationManager</interfacename> processes each
The configured <interfacename>AuthenticationManager</interfacename> authentication request. The destination following a successful authentication or an
processes each authentication request. The destination following a successful authentication authentication failure is controlled by the
or an authentication failure is controlled by the <interfacename>AuthenticationSuccessHandler</interfacename> <interfacename>AuthenticationSuccessHandler</interfacename> and
and <interfacename>AuthenticationFailureHandler</interfacename> interfaces, respectively. <interfacename>AuthenticationFailureHandler</interfacename> interfaces, respectively.
The filter has properties which allow you to set these The filter has properties which allow you to set these <footnote>
<footnote><para>In versions prior to 3.0, the application flow at this point had evolved to a stage <para>In versions prior to 3.0, the application flow at this point had evolved to a
was controlled by a mix of properties on this class and strategy plugins. The 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. decision was made for 3.0 to refactor the code to make these two strategies entirely
</para></footnote>. responsible. </para>
Some standard implementations are supplied for these such as </footnote>. Some standard implementations are supplied for these such as
<classname>SimpleUrlAuthenticationSuccessHandler</classname>, <classname>SimpleUrlAuthenticationSuccessHandler</classname>,
<classname>SavedRequestAwareAuthenticationSuccessHandler</classname>, <classname>SavedRequestAwareAuthenticationSuccessHandler</classname>,
<classname>SimpleUrlAuthenticationFailureHandler</classname> and <classname>SimpleUrlAuthenticationFailureHandler</classname> and
<classname>ExceptionMappingAuthenticationFailureHandler</classname>. Have a look at the Javadoc <classname>ExceptionMappingAuthenticationFailureHandler</classname>. Have a look at the
for these classes to see how they work. Javadoc for these classes to see how they work. </para>
</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
the user to the appropriate destination. By default a <classname>SavedRequestAwareAuthenticationSuccessHandler</classname> to the appropriate 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 used, which
login. means that the user will be redirected to the original destination they requested before
<note> they were asked to login. <note>
<para> <para> The <classname>ExceptionTranslationFilter</classname> caches the original request
The <classname>ExceptionTranslationFilter</classname> caches the original request a user makes. a user makes. When the user authenticates, the request handler makes use of this
When the user authenticates, the request handler makes use of this cached request to obtain the original cached request to obtain the original URL and redirect to it. The original request
URL and redirect to it. The original request is then rebuilt and used as an alternative. is then rebuilt and used as an alternative. </para>
</para> </note> If authentication fails, the configured
</note> <interfacename>AuthenticationFailureHandler</interfacename> will be invoked. </para>
If authentication fails, the configured <interfacename>AuthenticationFailureHandler</interfacename> will be invoked.
</para>
</section> </section>
</chapter> </chapter>

View File

@ -25,8 +25,8 @@
targets. <quote>Authentication</quote> is the process of establishing a principal is who targets. <quote>Authentication</quote> is the process of establishing a principal is who
they claim to be (a <quote>principal</quote> generally means a user, device or some they claim to be (a <quote>principal</quote> generally means a user, device or some
other system which can perform an action in your application). other system which can perform an action in your application).
<quote>Authorization</quote> refers to the process of deciding whether a principal <quote>Authorization</quote> refers to the process of deciding whether a principal is
is allowed to perform an action within your application. To arrive at the point where an allowed to perform an action within your application. To arrive at the point where an
authorization decision is needed, the identity of the principal has already been authorization decision is needed, the identity of the principal has already been
established by the authentication process. These concepts are common, and not at all established by the authentication process. These concepts are common, and not at all
specific to Spring Security. </para> specific to Spring Security. </para>
@ -134,8 +134,8 @@
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para>(* Denotes provided by a third party; check our <link <para>(* Denotes provided by a third party; check our <link
xlink:href="http://acegisecurity.org/powering.html">integration page</link> for xlink:href="http://acegisecurity.org/powering.html">integration page</link> for links to
links to the latest details)</para> the latest details)</para>
<para>Many independent software vendors (ISVs) adopt Spring Security because of this <para>Many independent software vendors (ISVs) adopt Spring Security because of this
significant choice of flexible authentication models. Doing so allows them to quickly significant choice of flexible authentication models. Doing so allows them to quickly
integrate their solutions with whatever their end clients need, without undertaking a integrate their solutions with whatever their end clients need, without undertaking a
@ -205,9 +205,9 @@
<literal>http://apr.apache.org/versioning.html</literal>. We quote the introduction <literal>http://apr.apache.org/versioning.html</literal>. We quote the introduction
contained on that page for your convenience:</para> contained on that page for your convenience:</para>
<para><quote>Versions are denoted using a standard triplet of integers: MAJOR.MINOR.PATCH. <para><quote>Versions are denoted using a standard triplet of integers: MAJOR.MINOR.PATCH.
The basic intent is that MAJOR versions are incompatible, large-scale upgrades of The basic intent is that MAJOR versions are incompatible, large-scale upgrades of the
the API. MINOR versions retain source and binary compatibility with older minor API. MINOR versions retain source and binary compatibility with older minor versions,
versions, and changes in the PATCH level are perfectly compatible, forwards and and changes in the PATCH level are perfectly compatible, forwards and
backwards.</quote></para> backwards.</quote></para>
</section> </section>
<section xml:id="get-spring-security"> <section xml:id="get-spring-security">
@ -215,8 +215,8 @@
<para>You can get hold of Spring Security in several ways. You can download a packaged <para>You can get hold of Spring Security in several ways. You can download a packaged
distribution from the main Spring <link distribution from the main Spring <link
xlink:href="http://www.springsource.com/download/community?project=Spring%20Security" xlink:href="http://www.springsource.com/download/community?project=Spring%20Security"
>download page</link>, download individual jars (and sample WAR files) from the >download page</link>, download individual jars (and sample WAR files) from the Maven
Maven Central repository (or a SpringSource Maven repository for snapshot and milestone Central repository (or a SpringSource Maven repository for snapshot and milestone
releases) or, alternatively, you can build the project from source yourself. See the releases) or, alternatively, you can build the project from source yourself. See the
project web site for more details. </para> project web site for more details. </para>
<section xml:id="modules"> <section xml:id="modules">
@ -233,8 +233,23 @@
<para>Contains core authentication and access-contol classes and interfaces, <para>Contains core authentication and access-contol classes and interfaces,
remoting support and basic provisioning APIs. Required by any application which remoting support and basic provisioning APIs. Required by any application which
uses Spring Security. Supports standalone applications, remote clients, method uses Spring Security. Supports standalone applications, remote clients, method
(service layer) security and JDBC user provisioning. Contains the top-level (service layer) security and JDBC user provisioning. Contains the top-level packages:<itemizedlist>
packages:<itemizedlist><listitem><para><literal>org.springframework.security.core</literal></para></listitem><listitem><para><literal>org.springframework.security.access</literal></para></listitem><listitem><para><literal>org.springframework.security.authentication</literal></para></listitem><listitem><para><literal>org.springframework.security.provisioning</literal></para></listitem><listitem><para><literal>org.springframework.security.remoting</literal></para></listitem></itemizedlist></para> <listitem>
<para><literal>org.springframework.security.core</literal></para>
</listitem>
<listitem>
<para><literal>org.springframework.security.access</literal></para>
</listitem>
<listitem>
<para><literal>org.springframework.security.authentication</literal></para>
</listitem>
<listitem>
<para><literal>org.springframework.security.provisioning</literal></para>
</listitem>
<listitem>
<para><literal>org.springframework.security.remoting</literal></para>
</listitem>
</itemizedlist></para>
</section> </section>
<section xml:id="spring-security-web"> <section xml:id="spring-security-web">
<title>Web - <literal>spring-security-web.jar</literal></title> <title>Web - <literal>spring-security-web.jar</literal></title>

View File

@ -1,36 +1,38 @@
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="jaas"> <chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="jaas">
<info><title>Java Authentication and Authorization Service (JAAS) Provider</title></info> <info>
<title>Java Authentication and Authorization Service (JAAS) Provider</title>
</info>
<section xml:id="jaas-overview"> <section xml:id="jaas-overview">
<info><title>Overview</title></info> <info>
<para>Spring Security provides a package able to delegate <title>Overview</title>
authentication requests to the Java Authentication and Authorization </info>
Service (JAAS). This package is discussed in detail below.</para> <para>Spring Security provides a package able to delegate authentication requests to the
Java Authentication and Authorization Service (JAAS). This package is discussed in
detail below.</para>
<para>Central to JAAS operation are login configuration files. To <para>Central to JAAS operation are login configuration files. To learn more about JAAS
learn more about JAAS login configuration files, consult the JAAS login configuration files, consult the JAAS reference documentation available from Sun
reference documentation available from Sun Microsystems. We expect you Microsystems. We expect you to have a basic understanding of JAAS and its login
to have a basic understanding of JAAS and its login configuration file configuration file syntax in order to understand this section.</para>
syntax in order to understand this section.</para>
</section> </section>
<section xml:id="jaas-config"> <section xml:id="jaas-config">
<info><title>Configuration</title></info> <info>
<para>The <literal>JaasAuthenticationProvider</literal> attempts to <title>Configuration</title>
authenticate a users principal and credentials through JAAS.</para> </info>
<para>The <literal>JaasAuthenticationProvider</literal> attempts to authenticate a users
principal and credentials through JAAS.</para>
<para>Lets assume we have a JAAS login configuration file, <para>Lets assume we have a JAAS login configuration file,
<literal>/WEB-INF/login.conf</literal>, with the following <literal>/WEB-INF/login.conf</literal>, with the following contents:
contents: <programlisting>
<programlisting>
JAASTest { JAASTest {
sample.SampleLoginModule required; sample.SampleLoginModule required;
};</programlisting></para> };</programlisting></para>
<para>Like all Spring Security beans, the <para>Like all Spring Security beans, the <classname>JaasAuthenticationProvider</classname>
<classname>JaasAuthenticationProvider</classname> is configured via the is configured via the application context. The following definitions would correspond to
application context. The following definitions would correspond to the the above JAAS login configuration file: <programlisting><![CDATA[
above JAAS login configuration file:
<programlisting><![CDATA[
<bean id="jaasAuthenticationProvider" <bean id="jaasAuthenticationProvider"
class="org.springframework.security.authentication.jaas.JaasAuthenticationProvider"> class="org.springframework.security.authentication.jaas.JaasAuthenticationProvider">
<property name="loginConfig" value="/WEB-INF/login.conf"/> <property name="loginConfig" value="/WEB-INF/login.conf"/>
@ -55,82 +57,76 @@ JAASTest {
<interfacename>AuthorityGranter</interfacename>s are discussed below.</para> <interfacename>AuthorityGranter</interfacename>s are discussed below.</para>
<section xml:id="jaas-callbackhandler"> <section xml:id="jaas-callbackhandler">
<info><title xml:id="jaas-callback-handler">JAAS CallbackHandler</title></info> <info>
<title xml:id="jaas-callback-handler">JAAS CallbackHandler</title>
</info>
<para>Most JAAS <literal>LoginModule</literal>s require a callback <para>Most JAAS <literal>LoginModule</literal>s require a callback of some sort. These
of some sort. These callbacks are usually used to obtain the callbacks are usually used to obtain the username and password from the user.</para>
username and password from the user.</para>
<para>In a Spring Security deployment, Spring Security is <para>In a Spring Security deployment, Spring Security is responsible for this user
responsible for this user interaction (via the authentication interaction (via the authentication mechanism). Thus, by the time the authentication
mechanism). Thus, by the time the authentication request is request is delegated through to JAAS, Spring Security's authentication mechanism
delegated through to JAAS, Spring Security's authentication will already have fully-populated an <interfacename>Authentication</interfacename>
mechanism will already have fully-populated an object containing all the information required by the JAAS
<interfacename>Authentication</interfacename> object containing all the
information required by the JAAS
<literal>LoginModule</literal>.</para> <literal>LoginModule</literal>.</para>
<para>Therefore, the JAAS package for Spring Security provides two <para>Therefore, the JAAS package for Spring Security provides two default callback
default callback handlers, handlers, <literal>JaasNameCallbackHandler</literal> and
<literal>JaasNameCallbackHandler</literal> and <literal>JaasPasswordCallbackHandler</literal>. Each of these callback handlers
<literal>JaasPasswordCallbackHandler</literal>. Each of these implement <literal>JaasAuthenticationCallbackHandler</literal>. In most cases these
callback handlers implement callback handlers can simply be used without understanding the internal
<literal>JaasAuthenticationCallbackHandler</literal>. In most cases mechanics.</para>
these callback handlers can simply be used without understanding the
internal mechanics.</para>
<para>For those needing full control over the callback behavior, <para>For those needing full control over the callback behavior, internally
internally <literal>JaasAuthenticationProvider</literal> wraps these <literal>JaasAuthenticationProvider</literal> wraps these
<literal>JaasAuthenticationCallbackHandler</literal>s with an <literal>JaasAuthenticationCallbackHandler</literal>s with an
<literal>InternalCallbackHandler</literal>. The <literal>InternalCallbackHandler</literal>. The
<literal>InternalCallbackHandler</literal> is the class that <literal>InternalCallbackHandler</literal> is the class that actually implements
actually implements JAAS normal <literal>CallbackHandler</literal> JAAS normal <literal>CallbackHandler</literal> interface. Any time that the JAAS
interface. Any time that the JAAS <literal>LoginModule</literal> is <literal>LoginModule</literal> is used, it is passed a list of application context
used, it is passed a list of application context configured configured <literal>InternalCallbackHandler</literal>s. If the
<literal>InternalCallbackHandler</literal>s. If the
<literal>LoginModule</literal> requests a callback against the <literal>LoginModule</literal> requests a callback against the
<literal>InternalCallbackHandler</literal>s, the callback is in-turn <literal>InternalCallbackHandler</literal>s, the callback is in-turn passed to the
passed to the <literal>JaasAuthenticationCallbackHandler</literal>s <literal>JaasAuthenticationCallbackHandler</literal>s being wrapped.</para>
being wrapped.</para>
</section> </section>
<section xml:id="jaas-authoritygranter"> <section xml:id="jaas-authoritygranter">
<info><title xml:id="jaas-authority-granter">JAAS AuthorityGranter</title></info> <info>
<title xml:id="jaas-authority-granter">JAAS AuthorityGranter</title>
</info>
<para>JAAS works with principals. Even "roles" are represented as <para>JAAS works with principals. Even "roles" are represented as principals in JAAS.
principals in JAAS. Spring Security, on the other hand, works with Spring Security, on the other hand, works with
<interfacename>Authentication</interfacename> objects. Each <interfacename>Authentication</interfacename> objects. Each
<interfacename>Authentication</interfacename> object contains a single <interfacename>Authentication</interfacename> object contains a single principal,
principal, and multiple <interfacename>GrantedAuthority</interfacename>[]s. To and multiple <interfacename>GrantedAuthority</interfacename>[]s. To facilitate
facilitate mapping between these different concepts, Spring mapping between these different concepts, Spring Security's JAAS package includes an
Security's JAAS package includes an
<literal>AuthorityGranter</literal> interface.</para> <literal>AuthorityGranter</literal> interface.</para>
<para>An <literal>AuthorityGranter</literal> is responsible for <para>An <literal>AuthorityGranter</literal> is responsible for inspecting a JAAS
inspecting a JAAS principal and returning a set of principal and returning a set of <literal>String</literal>s, representing the
<literal>String</literal>s, representing the authorities assigned to the principal. authorities assigned to the principal. For each returned authority string, the
For each returned authority string, the
<classname>JaasAuthenticationProvider</classname> creates a <classname>JaasAuthenticationProvider</classname> creates a
<classname>JaasGrantedAuthority</classname> (which implements Spring <classname>JaasGrantedAuthority</classname> (which implements Spring Securitys
Securitys <interfacename>GrantedAuthority</interfacename> interface) containing <interfacename>GrantedAuthority</interfacename> interface) containing the authority
the authority string and the JAAS principal that the string and the JAAS principal that the
<interfacename>AuthorityGranter</interfacename> was passed. The <interfacename>AuthorityGranter</interfacename> was passed. The
<classname>JaasAuthenticationProvider</classname> obtains the JAAS <classname>JaasAuthenticationProvider</classname> obtains the JAAS principals by
principals by firstly successfully authenticating the users firstly successfully authenticating the users credentials using the JAAS
credentials using the JAAS <literal>LoginModule</literal>, and then <literal>LoginModule</literal>, and then accessing the
accessing the <literal>LoginContext</literal> it returns. A call to <literal>LoginContext</literal> it returns. A call to
<literal>LoginContext.getSubject().getPrincipals()</literal> is <literal>LoginContext.getSubject().getPrincipals()</literal> is made, with each
made, with each resulting principal passed to each resulting principal passed to each <interfacename>AuthorityGranter</interfacename>
<interfacename>AuthorityGranter</interfacename> defined against the defined against the
<literal>JaasAuthenticationProvider.setAuthorityGranters(List)</literal> <literal>JaasAuthenticationProvider.setAuthorityGranters(List)</literal>
property.</para> property.</para>
<para>Spring Security does not include any production <para>Spring Security does not include any production
<interfacename>AuthorityGranter</interfacename>s given that every JAAS principal <interfacename>AuthorityGranter</interfacename>s given that every JAAS principal has
has an implementation-specific meaning. However, there is a an implementation-specific meaning. However, there is a
<literal>TestAuthorityGranter</literal> in the unit tests that <literal>TestAuthorityGranter</literal> in the unit tests that demonstrates a simple
demonstrates a simple <literal>AuthorityGranter</literal> <literal>AuthorityGranter</literal> implementation.</para>
implementation.</para>
</section> </section>
</section> </section>
</chapter> </chapter>

View File

@ -17,12 +17,11 @@
following link provides a good introduction to the concepts involved and a guide to following link provides a good introduction to the concepts involved and a guide to
setting up a directory using the free LDAP server OpenLDAP: <uri setting up a directory using the free LDAP server OpenLDAP: <uri
xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="http://www.zytrax.com/books/ldap/" xlink:href="http://www.zytrax.com/books/ldap/">http://www.zytrax.com/books/ldap/</uri>.
>http://www.zytrax.com/books/ldap/</uri>. Some familiarity with the JNDI APIs used Some familiarity with the JNDI APIs used to access LDAP from Java may also be useful. We
to access LDAP from Java may also be useful. We don't use any third-party LDAP libraries don't use any third-party LDAP libraries (Mozilla, JLDAP etc.) in the LDAP provider, but
(Mozilla, JLDAP etc.) in the LDAP provider, but extensive use is made of Spring LDAP, so extensive use is made of Spring LDAP, so some familiarity with that project may be
some familiarity with that project may be useful if you plan on adding your own useful if you plan on adding your own customizations.</para>
customizations.</para>
</section> </section>
<section> <section>
<info> <info>
@ -31,9 +30,9 @@
<para> LDAP authentication in Spring Security can be roughly divided into the following <para> LDAP authentication in Spring Security can be roughly divided into the following
stages. <orderedlist inheritnum="ignore" continuation="restarts"> stages. <orderedlist inheritnum="ignore" continuation="restarts">
<listitem> <listitem>
<para>Obtaining the unique LDAP <quote>Distinguished Name</quote>, or DN, from <para>Obtaining the unique LDAP <quote>Distinguished Name</quote>, or DN, from the
the login name. This will often mean performing a search in the directory, login name. This will often mean performing a search in the directory, unless
unless the exact mapping of usernames to DNs is known in advance.</para> the exact mapping of usernames to DNs is known in advance.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>Authenticating the user, either by binding as that user or by performing a <para>Authenticating the user, either by binding as that user or by performing a
@ -72,8 +71,8 @@
<ldap-server root="dc=springframework,dc=org"/> <ldap-server root="dc=springframework,dc=org"/>
]]> ]]>
</programlisting> Here we've specified that the root DIT of the directory should be </programlisting> Here we've specified that the root DIT of the directory should be
<quote>dc=springframework,dc=org</quote>, which is the default. Used this way, <quote>dc=springframework,dc=org</quote>, which is the default. Used this way, the
the namespace parser will create an embedded Apache Directory server and scan the namespace parser will create an embedded Apache Directory server and scan the
classpath for any LDIF files, which it will attempt to load into the server. You can classpath for any LDIF files, which it will attempt to load into the server. You can
customize this behaviour using the <literal>ldif</literal> attribute, which defines customize this behaviour using the <literal>ldif</literal> attribute, which defines
an LDIF resource to be loaded: <programlisting><![CDATA[ an LDIF resource to be loaded: <programlisting><![CDATA[
@ -112,34 +111,30 @@
<para> How authorities are loaded from groups in the LDAP directory is controlled by the <para> How authorities are loaded from groups in the LDAP directory is controlled by the
following attributes. <itemizedlist> following attributes. <itemizedlist>
<listitem> <listitem>
<para> <para> <literal>group-search-base</literal>. Defines the part of the directory
<literal>group-search-base</literal>. Defines the part of the directory
tree under which group searches should be performed.</para> tree under which group searches should be performed.</para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para> <literal>group-role-attribute</literal>. The attribute which contains the
<literal>group-role-attribute</literal>. The attribute which contains name of the authority defined by the group entry. Defaults to
the name of the authority defined by the group entry. Defaults to <literal>cn</literal> </para>
<literal>cn</literal>
</para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para> <literal>group-search-filter</literal>. The filter which is used to
<literal>group-search-filter</literal>. The filter which is used to
search for group membership. The default is search for group membership. The default is
<literal>uniqueMember={0}</literal>, corresponding to the <literal>uniqueMember={0}</literal>, corresponding to the
<literal>groupOfUniqueMembers</literal> LDAP class. In this case, <literal>groupOfUniqueMembers</literal> LDAP class. In this case, the
the substituted parameter is the full distinguished name of the user. substituted parameter is the full distinguished name of the user. The
The parameter <literal>{1}</literal> can be used if you want to filter parameter <literal>{1}</literal> can be used if you want to filter on the
on the login name.</para> login name.</para>
</listitem> </listitem>
</itemizedlist> So if we used the following configuration <programlisting><![CDATA[ </itemizedlist> So if we used the following configuration <programlisting><![CDATA[
<ldap-authentication-provider user-dn-pattern="uid={0},ou=people" <ldap-authentication-provider user-dn-pattern="uid={0},ou=people"
group-search-base="ou=groups" /> group-search-base="ou=groups" />
]]></programlisting> and authenticated successfully as user <quote>ben</quote>, the subsequent ]]></programlisting> and authenticated successfully as user <quote>ben</quote>, the subsequent
loading of authorities would perform a search under the directory entry loading of authorities would perform a search under the directory entry
<literal>ou=groups,dc=springframework,dc=org</literal>, looking for entries <literal>ou=groups,dc=springframework,dc=org</literal>, looking for entries which
which contain the attribute <literal>uniqueMember</literal> with value contain the attribute <literal>uniqueMember</literal> with value
<literal>uid=ben,ou=people,dc=springframework,dc=org</literal>. By default the <literal>uid=ben,ou=people,dc=springframework,dc=org</literal>. By default the
authority names will have the prefix <literal>ROLE_</literal> prepended. You can authority names will have the prefix <literal>ROLE_</literal> prepended. You can
change this using the <literal>role-prefix</literal> attribute. If you don't want change this using the <literal>role-prefix</literal> attribute. If you don't want
@ -173,16 +168,14 @@
to read them with the user's own permissions.</para> to read them with the user's own permissions.</para>
<para>There are currently two authentication strategies supplied with Spring Security: <itemizedlist> <para>There are currently two authentication strategies supplied with Spring Security: <itemizedlist>
<listitem> <listitem>
<para>Authentication directly to the LDAP server ("bind" <para>Authentication directly to the LDAP server ("bind" authentication).</para>
authentication).</para>
</listitem> </listitem>
<listitem> <listitem>
<para>Password comparison, where the password supplied by the user is <para>Password comparison, where the password supplied by the user is compared
compared with the one stored in the repository. This can either be done with the one stored in the repository. This can either be done by retrieving
by retrieving the value of the password attribute and checking it the value of the password attribute and checking it locally or by performing
locally or by performing an LDAP "compare" operation, where the supplied an LDAP "compare" operation, where the supplied password is passed to the
password is passed to the server for comparison and the real password server for comparison and the real password value is never retrieved.</para>
value is never retrieved.</para>
</listitem> </listitem>
</itemizedlist></para> </itemizedlist></para>
<section xml:id="ldap-ldap-authenticators-common"> <section xml:id="ldap-ldap-authenticators-common">
@ -193,32 +186,31 @@
distinguished name (DN) has to be obtained from the login name supplied to the distinguished name (DN) has to be obtained from the login name supplied to the
application. This can be done either by simple pattern-matching (by setting the application. This can be done either by simple pattern-matching (by setting the
<property>setUserDnPatterns</property> array property) or by setting the <property>setUserDnPatterns</property> array property) or by setting the
<property>userSearch</property> property. For the DN pattern-matching <property>userSearch</property> property. For the DN pattern-matching approach,
approach, a standard Java pattern format is used, and the login name will be a standard Java pattern format is used, and the login name will be substituted
substituted for the parameter <parameter>{0}</parameter>. The pattern should be for the parameter <parameter>{0}</parameter>. The pattern should be relative to
relative to the DN that the configured the DN that the configured
<interfacename>SpringSecurityContextSource</interfacename> will bind to (see <interfacename>SpringSecurityContextSource</interfacename> will bind to (see the
the section on <link linkend="ldap-context-source">connecting to the LDAP section on <link linkend="ldap-context-source">connecting to the LDAP
server</link> for more information on this). For example, if you are using server</link> for more information on this). For example, if you are using an
an LDAP server with the URL LDAP server with the URL
<literal>ldap://monkeymachine.co.uk/dc=springframework,dc=org</literal>, and <literal>ldap://monkeymachine.co.uk/dc=springframework,dc=org</literal>, and
have a pattern <literal>uid={0},ou=greatapes</literal>, then a login name of have a pattern <literal>uid={0},ou=greatapes</literal>, then a login name of
"gorilla" will map to a DN "gorilla" will map to a DN
<literal>uid=gorilla,ou=greatapes,dc=springframework,dc=org</literal>. Each <literal>uid=gorilla,ou=greatapes,dc=springframework,dc=org</literal>. Each
configured DN pattern will be tried in turn until a match is found. For configured DN pattern will be tried in turn until a match is found. For
information on using a search, see the section on <link information on using a search, see the section on <link
linkend="ldap-searchobjects">search objects</link> below. A combination of linkend="ldap-searchobjects">search objects</link> below. A combination of the
the two approaches can also be used - the patterns will be checked first and if two approaches can also be used - the patterns will be checked first and if no
no matching DN is found, the search will be used.</para> matching DN is found, the search will be used.</para>
</section> </section>
<section xml:id="ldap-ldap-authenticators-bind"> <section xml:id="ldap-ldap-authenticators-bind">
<info> <info>
<title>BindAuthenticator</title> <title>BindAuthenticator</title>
</info> </info>
<para>The class <classname>BindAuthenticator</classname> in the package <para>The class <classname>BindAuthenticator</classname> in the package
<filename>org.springframework.security.ldap.authentication</filename> <filename>org.springframework.security.ldap.authentication</filename> implements
implements the bind authentication strategy. It simply attempts to bind as the the bind authentication strategy. It simply attempts to bind as the user.</para>
user.</para>
</section> </section>
<section xml:id="ldap-ldap-authenticators-password"> <section xml:id="ldap-ldap-authenticators-password">
<info> <info>
@ -254,16 +246,15 @@
<info> <info>
<title>LDAP Search Objects</title> <title>LDAP Search Objects</title>
</info> </info>
<para>Often a more complicated strategy than simple DN-matching is required to <para>Often a more complicated strategy than simple DN-matching is required to locate a
locate a user entry in the directory. This can be encapsulated in an user entry in the directory. This can be encapsulated in an
<interfacename>LdapUserSearch</interfacename> instance which can be supplied to <interfacename>LdapUserSearch</interfacename> instance which can be supplied to the
the authenticator implementations, for example, to allow them to locate a user. The authenticator implementations, for example, to allow them to locate a user. The
supplied implementation is <classname>FilterBasedLdapUserSearch</classname>.</para> supplied implementation is <classname>FilterBasedLdapUserSearch</classname>.</para>
<section xml:id="ldap-searchobjects-filter"> <section xml:id="ldap-searchobjects-filter">
<info> <info>
<title xml:id="ldap-searchobjects-filter-based"> <title xml:id="ldap-searchobjects-filter-based">
<classname>FilterBasedLdapUserSearch</classname> <classname>FilterBasedLdapUserSearch</classname> </title>
</title>
</info> </info>
<para>This bean uses an LDAP filter to match the user object in the directory. The <para>This bean uses an LDAP filter to match the user object in the directory. The
process is explained in the Javadoc for the corresponding search method on the process is explained in the Javadoc for the corresponding search method on the
@ -281,11 +272,11 @@
<classname>LdapAuthenticationProvider</classname> will attempt to load a set of <classname>LdapAuthenticationProvider</classname> will attempt to load a set of
authorities for the user by calling the configured authorities for the user by calling the configured
<interfacename>LdapAuthoritiesPopulator</interfacename> bean. The <interfacename>LdapAuthoritiesPopulator</interfacename> bean. The
<classname>DefaultLdapAuthoritiesPopulator</classname> is an implementation <classname>DefaultLdapAuthoritiesPopulator</classname> is an implementation which
which will load the authorities by searching the directory for groups of which the will load the authorities by searching the directory for groups of which the user is
user is a member (typically these will be <literal>groupOfNames</literal> or a member (typically these will be <literal>groupOfNames</literal> or
<literal>groupOfUniqueNames</literal> entries in the directory). Consult the <literal>groupOfUniqueNames</literal> entries in the directory). Consult the Javadoc
Javadoc for this class for more details on how it works. </para> for this class for more details on how it works. </para>
<para>If you want to use LDAP only for authentication, but load the authorities from a <para>If you want to use LDAP only for authentication, but load the authorities from a
difference source (such as a database) then you can provide your own implementation difference source (such as a database) then you can provide your own implementation
of this interface and inject that instead.</para> of this interface and inject that instead.</para>
@ -331,8 +322,8 @@
filter <literal>(member=&lt;user's-DN&gt;)</literal>. The role name will be taken filter <literal>(member=&lt;user's-DN&gt;)</literal>. The role name will be taken
from the <quote>ou</quote> attribute of each match.</para> from the <quote>ou</quote> attribute of each match.</para>
<para>To configure a user search object, which uses the filter <para>To configure a user search object, which uses the filter
<literal>(uid=&lt;user-login-name&gt;)</literal> for use instead of the <literal>(uid=&lt;user-login-name&gt;)</literal> for use instead of the DN-pattern
DN-pattern (or in addition to it), you would configure the following bean <programlisting><![CDATA[ (or in addition to it), you would configure the following bean <programlisting><![CDATA[
<bean id="userSearch" <bean id="userSearch"
class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch"> class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg index="0" value=""/> <constructor-arg index="0" value=""/>
@ -355,25 +346,25 @@
<interfacename>UserDetailsService</interfacename>, a common requirement is to be <interfacename>UserDetailsService</interfacename>, a common requirement is to be
able to customize this implementation and add extra properties. When using LDAP, able to customize this implementation and add extra properties. When using LDAP,
these will normally be attributes from the user entry. The creation of the these will normally be attributes from the user entry. The creation of the
<interfacename>UserDetails</interfacename> object is controlled by the <interfacename>UserDetails</interfacename> object is controlled by the provider's
provider's <interfacename>UserDetailsContextMapper</interfacename> strategy, which <interfacename>UserDetailsContextMapper</interfacename> strategy, which is
is responsible for mapping user objects to and from LDAP context data: <programlisting><![CDATA[ responsible for mapping user objects to and from LDAP context data: <programlisting><![CDATA[
public interface UserDetailsContextMapper { public interface UserDetailsContextMapper {
UserDetails mapUserFromContext(DirContextOperations ctx, String username, UserDetails mapUserFromContext(DirContextOperations ctx, String username,
Collection<GrantedAuthority> authorities); Collection<GrantedAuthority> authorities);
void mapUserToContext(UserDetails user, DirContextAdapter ctx); void mapUserToContext(UserDetails user, DirContextAdapter ctx);
}]]> }]]>
</programlisting> Only the first method is relevant for </programlisting> Only the first method is relevant for authentication. If you
authentication. If you provide an implementation of this interface, you can control provide an implementation of this interface, you can control exactly how the
exactly how the UserDetails object is created. The first parameter is an instance of UserDetails object is created. The first parameter is an instance of Spring LDAP's
Spring LDAP's <interfacename>DirContextOperations</interfacename> which gives you <interfacename>DirContextOperations</interfacename> which gives you access to the
access to the LDAP attributes which were loaded. The <literal>username</literal> LDAP attributes which were loaded. The <literal>username</literal> parameter is the
parameter is the name used to authenticate and the final parameter is the collection name used to authenticate and the final parameter is the collection of authorities
of authorities loaded for the user. </para> loaded for the user. </para>
<para> The way the context data is loaded varies slightly depending on the type of <para> The way the context data is loaded varies slightly depending on the type of
authentication you are using. With the <classname>BindAuthenticator</classname>, authentication you are using. With the <classname>BindAuthenticator</classname>, the
the context returned from the bind operation will be used to read the attributes, context returned from the bind operation will be used to read the attributes,
otherwise the data will be read using the standard context obtained from the otherwise the data will be read using the standard context obtained from the
configured <interfacename>ContextSource</interfacename> (when a search is configured configured <interfacename>ContextSource</interfacename> (when a search is configured
to locate the user, this will be the data returned by the search object). </para> to locate the user, this will be the data returned by the search object). </para>

File diff suppressed because it is too large Load Diff

View File

@ -4,135 +4,147 @@
<info> <info>
<title>Pre-Authentication Scenarios</title> <title>Pre-Authentication Scenarios</title>
</info> </info>
<para> There are situations where you want to use Spring Security for authorization, but the user <para> There are situations where you want to use Spring Security for authorization, but the
has already been reliably authenticated by some external system prior to accessing the user has already been reliably authenticated by some external system prior to accessing the
application. We refer to these situations as <quote>pre-authenticated</quote> scenarios. application. We refer to these situations as <quote>pre-authenticated</quote> scenarios.
Examples include X.509, Siteminder and authentication by the J2EE container in which the Examples include X.509, Siteminder and authentication by the J2EE container in which the
application is running. When using pre-authentication, Spring Security has to application is running. When using pre-authentication, Spring Security has to <orderedlist>
<orderedlist><listitem><para>Identify the user making the request. <listitem>
</para></listitem><listitem><para>Obtain the authorities for the <para>Identify the user making the request. </para>
user.</para></listitem></orderedlist>The details will depend on the external authentication </listitem>
mechanism. A user might be identified by their certificate information in the case of X.509, or <listitem>
by an HTTP request header in the case of Siteminder. If relying on container authentication, the <para>Obtain the authorities for the user.</para>
user will be identified by calling the <methodname>getUserPrincipal()</methodname> method on the </listitem>
incoming HTTP request. In some cases, the external mechanism may supply role/authority </orderedlist>The details will depend on the external authentication mechanism. A user might
information for the user but in others the authorities must be obtained from a separate source, be identified by their certificate information in the case of X.509, or by an HTTP request
such as a <interfacename>UserDetailsService</interfacename>. </para> header in the case of Siteminder. If relying on container authentication, the user will be
identified by calling the <methodname>getUserPrincipal()</methodname> method on the incoming
HTTP request. In some cases, the external mechanism may supply role/authority information
for the user but in others the authorities must be obtained from a separate source, such as
a <interfacename>UserDetailsService</interfacename>. </para>
<section> <section>
<title>Pre-Authentication Framework Classes</title> <title>Pre-Authentication Framework Classes</title>
<para> Because most pre-authentication mechanisms follow the same pattern, Spring Security has a <para> Because most pre-authentication mechanisms follow the same pattern, Spring Security
set of classes which provide an internal framework for implementing pre-authenticated has a set of classes which provide an internal framework for implementing
authentication providers. This removes duplication and allows new implementations to be added pre-authenticated authentication providers. This removes duplication and allows new
in a structured fashion, without having to write everything from scratch. You don't need to implementations to be added in a structured fashion, without having to write everything
know about these classes if you want to use something like <link xlink:href="#x509">X.509 from scratch. You don't need to know about these classes if you want to use something
authentication</link>, as it already has a namespace configuration option which is simpler like <link xlink:href="#x509">X.509 authentication</link>, as it already has a namespace
to use and get started with. If you need to use explicit bean configuration or are planning on configuration option which is simpler to use and get started with. If you need to use
writing your own implementation then an understanding of how the provided implementations work explicit bean configuration or are planning on writing your own implementation then an
will be useful. You will find classes under the understanding of how the provided implementations work will be useful. You will find
<package>org.springframework.security.web.authentication.preauth</package>. We just provide classes under the
an outline here so you should consult the Javadoc and source where appropriate. </para> <package>org.springframework.security.web.authentication.preauth</package>. We just
provide an outline here so you should consult the Javadoc and source where appropriate. </para>
<section> <section>
<title>AbstractPreAuthenticatedProcessingFilter</title> <title>AbstractPreAuthenticatedProcessingFilter</title>
<para> This class will check the current contents of the security context and, if empty, it <para> This class will check the current contents of the security context and, if empty,
will attempt to extract user information from the HTTP request and submit it to the it will attempt to extract user information from the HTTP request and submit it to
<interfacename>AuthenticationManager</interfacename>. Subclasses override the following the <interfacename>AuthenticationManager</interfacename>. Subclasses override the
methods to obtain this information: following methods to obtain this information:
<programlisting language="java"> <programlisting language="java">
protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request); protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request);
protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request); protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request);
</programlisting> </programlisting>
After calling these, the filter will create a After calling these, the filter will create a
<classname>PreAuthenticatedAuthenticationToken</classname> containing the returned data <classname>PreAuthenticatedAuthenticationToken</classname> containing the returned
and submit it for authentication. By <quote>authentication</quote> here, we really just mean data and submit it for authentication. By <quote>authentication</quote> here, we
further processing to perhaps load the user's authorities, but the standard Spring Security really just mean further processing to perhaps load the user's authorities, but the
authentication architecture is followed. </para> standard Spring Security authentication architecture is followed. </para>
</section> </section>
<section> <section>
<title>AbstractPreAuthenticatedAuthenticationDetailsSource</title> <title>AbstractPreAuthenticatedAuthenticationDetailsSource</title>
<para> Like other Spring Security authentication filters, the pre-authentication filter has an <para> Like other Spring Security authentication filters, the pre-authentication filter
<literal>authenticationDetailsSource</literal> property which by default will create a has an <literal>authenticationDetailsSource</literal> property which by default will
<classname>WebAuthenticationDetails</classname> object to store additional information create a <classname>WebAuthenticationDetails</classname> object to store additional
such as the session-identifier and originating IP address in the <literal>details</literal> information such as the session-identifier and originating IP address in the
property of the <interfacename>Authentication</interfacename> object. In cases where user <literal>details</literal> property of the
role information can be obtained from the pre-authentication mechanism, the data is also <interfacename>Authentication</interfacename> object. In cases where user role
information can be obtained from the pre-authentication mechanism, the data is also
stored in this property. Subclasses of stored in this property. Subclasses of
<classname>AbstractPreAuthenticatedAuthenticationDetailsSource</classname> use an extended <classname>AbstractPreAuthenticatedAuthenticationDetailsSource</classname> use an
details object which implements the extended details object which implements the
<interfacename>GrantedAuthoritiesContainer</interfacename> interface, thus enabling the <interfacename>GrantedAuthoritiesContainer</interfacename> interface, thus enabling
authentication provider to read the authorities which were externally allocated to the user. the authentication provider to read the authorities which were externally allocated
We'll look at a concrete example next. </para> to the user. We'll look at a concrete example next. </para>
<section xml:id="j2ee-preauth-details"> <section xml:id="j2ee-preauth-details">
<title>J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource</title> <title>J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource</title>
<para> If the filter is configured with an <literal>authenticationDetailsSource</literal> <para> If the filter is configured with an
which is an instance of this class, the authority information is obtained by calling the <literal>authenticationDetailsSource</literal> which is an instance of this
<methodname>isUserInRole(String role)</methodname> method for each of a pre-determined class, the authority information is obtained by calling the
set of <quote>mappable roles</quote>. The class gets these from a configured <methodname>isUserInRole(String role)</methodname> method for each of a
<interfacename>MappableAttributesRetriever</interfacename>. Possible implementations pre-determined set of <quote>mappable roles</quote>. The class gets these from a
include hard-coding a list in the application context and reading the role information configured <interfacename>MappableAttributesRetriever</interfacename>. Possible
from the <literal>&lt;security-role&gt;</literal> information in a implementations include hard-coding a list in the application context and
<filename>web.xml</filename> file. The pre-authentication sample application uses the reading the role information from the <literal>&lt;security-role&gt;</literal>
latter approach. </para> information in a <filename>web.xml</filename> file. The pre-authentication
<para>There is an additional stage where the roles (or attributes) are mapped to Spring sample application uses the latter approach. </para>
Security <interfacename>GrantedAuthority</interfacename> objects using a configured <para>There is an additional stage where the roles (or attributes) are mapped to
<interfacename>Attributes2GrantedAuthoritiesMapper</interfacename>. The default will Spring Security <interfacename>GrantedAuthority</interfacename> objects using a
just add the usual <literal>ROLE_</literal> prefix to the names, but it gives you full configured <interfacename>Attributes2GrantedAuthoritiesMapper</interfacename>.
control over the behaviour. </para> The default will just add the usual <literal>ROLE_</literal> prefix to the
names, but it gives you full control over the behaviour. </para>
</section> </section>
</section> </section>
<section> <section>
<title>PreAuthenticatedAuthenticationProvider</title> <title>PreAuthenticatedAuthenticationProvider</title>
<para> The pre-authenticated provider has little more to do than load the <para> The pre-authenticated provider has little more to do than load the
<interfacename>UserDetails</interfacename> object for the user. It does this by delegating <interfacename>UserDetails</interfacename> object for the user. It does this by
to a <interfacename>AuthenticationUserDetailsService</interfacename>. The latter is similar delegating to a <interfacename>AuthenticationUserDetailsService</interfacename>. The
to the standard <interfacename>UserDetailsService</interfacename> but takes an latter is similar to the standard <interfacename>UserDetailsService</interfacename>
<interfacename>Authentication</interfacename> object rather than just user name: but takes an <interfacename>Authentication</interfacename> object rather than just
user name:
<programlisting language="java"> <programlisting language="java">
public interface AuthenticationUserDetailsService { public interface AuthenticationUserDetailsService {
UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException; UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException;
} }
</programlisting> </programlisting>
This interface may have also other uses but with pre-authentication it allows access to the This interface may have also other uses but with pre-authentication it allows access
authorities which were packaged in the <interfacename>Authentication</interfacename> object, to the authorities which were packaged in the
as we saw in the previous section. The <interfacename>Authentication</interfacename> object, as we saw in the previous
<classname>PreAuthenticatedGrantedAuthoritiesUserDetailsService</classname> class does section. The
this. Alternatively, it may delegate to a standard <classname>PreAuthenticatedGrantedAuthoritiesUserDetailsService</classname> class
does this. Alternatively, it may delegate to a standard
<interfacename>UserDetailsService</interfacename> via the <interfacename>UserDetailsService</interfacename> via the
<classname>UserDetailsByNameServiceWrapper</classname> implementation. </para> <classname>UserDetailsByNameServiceWrapper</classname> implementation. </para>
</section> </section>
<section> <section>
<title>Http403ForbiddenEntryPoint</title> <title>Http403ForbiddenEntryPoint</title>
<para> The <interfacename>AuthenticationEntryPoint</interfacename> was discussed in the <link <para> The <interfacename>AuthenticationEntryPoint</interfacename> was discussed in the
xlink:href="#tech-intro-auth-entry-point">technical overview</link> chapter. Normally it <link xlink:href="#tech-intro-auth-entry-point">technical overview</link> chapter.
is responsible for kick-starting the authentication process for an unauthenticated user Normally it is responsible for kick-starting the authentication process for an
(when they try to access a protected resource), but in the pre-authenticated case this unauthenticated user (when they try to access a protected resource), but in the
doesn't apply. You would only configure the pre-authenticated case this doesn't apply. You would only configure the
<classname>ExceptionTranslationFilter</classname> with an instance of this class if you <classname>ExceptionTranslationFilter</classname> with an instance of this class if
aren't using pre-authentication in combination with other authentication mechanisms. It will you aren't using pre-authentication in combination with other authentication
be called if the user is rejected by the mechanisms. It will be called if the user is rejected by the
<classname>AbstractPreAuthenticatedProcessingFilter</classname> resulting in a null <classname>AbstractPreAuthenticatedProcessingFilter</classname> resulting in a null
authentication. It always returns a <literal>403</literal>-forbidden response code if authentication. It always returns a <literal>403</literal>-forbidden response code
called. </para> if called. </para>
</section> </section>
</section> </section>
<section> <section>
<title>Concrete Implementations</title> <title>Concrete Implementations</title>
<para> X.509 authentication is covered in its <link xlink:href="#x509">own chapter</link>. Here <para> X.509 authentication is covered in its <link xlink:href="#x509">own chapter</link>.
we'll look at some classes which provide support for other pre-authenticated scenarios. </para> Here we'll look at some classes which provide support for other pre-authenticated
scenarios. </para>
<section> <section>
<title>Request-Header Authentication (Siteminder)</title> <title>Request-Header Authentication (Siteminder)</title>
<para> An external authentication system may supply information to the application by setting <para> An external authentication system may supply information to the application by
specific headers on the HTTP request. A well known example of this is Siteminder, which setting specific headers on the HTTP request. A well known example of this is
passes the username in a header called <literal>SM_USER</literal>. This mechanism is Siteminder, which passes the username in a header called <literal>SM_USER</literal>.
supported by the class <classname>RequestHeaderAuthenticationFilter</classname> which simply This mechanism is supported by the class
extracts the username from the header. It defaults to using the name <classname>RequestHeaderAuthenticationFilter</classname> which simply extracts the
<literal>SM_USER</literal> as the header name. See the Javadoc for more details. </para> username from the header. It defaults to using the name <literal>SM_USER</literal>
as the header name. See the Javadoc for more details. </para>
<tip> <tip>
<para>Note that when using a system like this, the framework performs no authentication <para>Note that when using a system like this, the framework performs no
checks at all and it is <emphasis>extremely</emphasis> important that the external system authentication checks at all and it is <emphasis>extremely</emphasis> important
is configured properly and protects all access to the application. If an attacker is able that the external system is configured properly and protects all access to the
to forge the headers in their original request without this being detected then they could application. If an attacker is able to forge the headers in their original
potentially choose any username they wished. </para> request without this being detected then they could potentially choose any
username they wished. </para>
</tip> </tip>
<section> <section>
<title>Siteminder Example Configuration</title> <title>Siteminder Example Configuration</title>
@ -162,27 +174,28 @@ class="org.springframework.security.web.authentication.preauth.PreAuthenticatedA
<security:authentication-provider ref="preauthAuthProvider" /> <security:authentication-provider ref="preauthAuthProvider" />
</security-authentication-manager> </security-authentication-manager>
]]> ]]>
</programlisting> We've assumed here that the security namespace is being used for </programlisting> We've assumed here that the security namespace is being used for configuration
configuration (hence the user of the <literal>custom-filter</literal>, (hence the user of the <literal>custom-filter</literal>,
<literal>authentication-manager</literal> and <literal>authentication-manager</literal> and
<literal>custom-authentication-provider</literal> elements (you can read more about them <literal>custom-authentication-provider</literal> elements (you can read more
in the <link xlink:href="ns-config">namespace chapter</link>). You would leave these out about them in the <link xlink:href="ns-config">namespace chapter</link>). You
of a traditional bean configuration. It's also assumed that you have added a would leave these out of a traditional bean configuration. It's also assumed
<interfacename>UserDetailsService</interfacename> (called that you have added a <interfacename>UserDetailsService</interfacename> (called
<quote>userDetailsService</quote>) to your configuration to load the user's roles. <quote>userDetailsService</quote>) to your configuration to load the user's
</para> roles. </para>
</section> </section>
</section> </section>
<section> <section>
<title>J2EE Container Authentication</title> <title>J2EE Container Authentication</title>
<para> The class <classname>J2eePreAuthenticatedProcessingFilter</classname> will extract the <para> The class <classname>J2eePreAuthenticatedProcessingFilter</classname> will
username from the <literal>userPrincipal</literal> property of the extract the username from the <literal>userPrincipal</literal> property of the
<interfacename>HttpServletRequest</interfacename>. Use of this filter would usually be <interfacename>HttpServletRequest</interfacename>. Use of this filter would usually
combined with the use of J2EE roles as described above in <xref be combined with the use of J2EE roles as described above in <xref
linkend="j2ee-preauth-details"/>. </para> linkend="j2ee-preauth-details"/>. </para>
<para> There is a sample application in the codebase which uses this approach, so get hold of <para> There is a sample application in the codebase which uses this approach, so get
the code from subversion and have a look at the application context file if you are hold of the code from subversion and have a look at the application context file if
interested. The code is in the <filename>samples/preauth</filename> directory. </para> you are interested. The code is in the <filename>samples/preauth</filename>
directory. </para>
</section> </section>
</section> </section>
</chapter> </chapter>

View File

@ -15,10 +15,9 @@
One uses hashing to preserve the security of cookie-based tokens and the other uses a One uses hashing to preserve the security of cookie-based tokens and the other uses a
database or other persistent storage mechanism to store the generated tokens. </para> database or other persistent storage mechanism to store the generated tokens. </para>
<para> Note that both implemementations require a <para> Note that both implemementations require a
<interfacename>UserDetailsService</interfacename>. If you are using an <interfacename>UserDetailsService</interfacename>. If you are using an authentication
authentication provider which doesn't use a provider which doesn't use a <interfacename>UserDetailsService</interfacename> (for
<interfacename>UserDetailsService</interfacename> (for example, the LDAP provider) example, the LDAP provider) then it won't work unless you also have a
then it won't work unless you also have a
<interfacename>UserDetailsService</interfacename> bean in your application context. <interfacename>UserDetailsService</interfacename> bean in your application context.
</para> </para>
</section> </section>
@ -63,12 +62,13 @@
<title>Persistent Token Approach</title> <title>Persistent Token Approach</title>
<para>This approach is based on the article <link <para>This approach is based on the article <link
xlink:href="http://jaspan.com/improved_persistent_login_cookie_best_practice" xlink:href="http://jaspan.com/improved_persistent_login_cookie_best_practice"
>http://jaspan.com/improved_persistent_login_cookie_best_practice</link> with some >http://jaspan.com/improved_persistent_login_cookie_best_practice</link> with some minor
minor modifications <footnote><para>Essentially, the username is not included in the modifications <footnote>
cookie, to prevent exposing a valid login name unecessarily. There is a <para>Essentially, the username is not included in the cookie, to prevent exposing a
discussion on this in the comments section of this article.</para></footnote>. valid login name unecessarily. There is a discussion on this in the comments section
To use the this approach with namespace configuration, you would supply a datasource of this article.</para>
reference: <programlisting><![CDATA[ </footnote>. To use the this approach with namespace configuration, you would supply a
datasource reference: <programlisting><![CDATA[
<http> <http>
... ...
<remember-me data-source-ref="someDataSource"/> <remember-me data-source-ref="someDataSource"/>
@ -91,10 +91,10 @@
</info> </info>
<para>Remember-me authentication is not used with basic authentication, given it is often <para>Remember-me authentication is not used with basic authentication, given it is often
not used with <literal>HttpSession</literal>s. Remember-me is used with not used with <literal>HttpSession</literal>s. Remember-me is used with
<literal>UsernamePasswordAuthenticationFilter</literal>, and is implemented via <literal>UsernamePasswordAuthenticationFilter</literal>, and is implemented via hooks in
hooks in the <literal>AbstractAuthenticationProcessingFilter</literal> superclass. The the <literal>AbstractAuthenticationProcessingFilter</literal> superclass. The hooks will
hooks will invoke a concrete <interfacename>RememberMeServices</interfacename> at the invoke a concrete <interfacename>RememberMeServices</interfacename> at the appropriate
appropriate times. The interface looks like this: times. The interface looks like this:
<programlisting language="java"> <programlisting language="java">
Authentication autoLogin(HttpServletRequest request, HttpServletResponse response); Authentication autoLogin(HttpServletRequest request, HttpServletResponse response);
void loginFail(HttpServletRequest request, HttpServletResponse response); void loginFail(HttpServletRequest request, HttpServletResponse response);
@ -122,12 +122,12 @@
<literal>RememberMeAuthenticationProvider</literal>. A <literal>key</literal> is <literal>RememberMeAuthenticationProvider</literal>. A <literal>key</literal> is
shared between this authentication provider and the shared between this authentication provider and the
<literal>TokenBasedRememberMeServices</literal>. In addition, <literal>TokenBasedRememberMeServices</literal>. In addition,
<literal>TokenBasedRememberMeServices</literal> requires A UserDetailsService <literal>TokenBasedRememberMeServices</literal> requires A UserDetailsService from
from which it can retrieve the username and password for signature comparison which it can retrieve the username and password for signature comparison purposes,
purposes, and generate the <literal>RememberMeAuthenticationToken</literal> to and generate the <literal>RememberMeAuthenticationToken</literal> to contain the
contain the correct <interfacename>GrantedAuthority</interfacename>[]s. Some sort of correct <interfacename>GrantedAuthority</interfacename>[]s. Some sort of logout
logout command should be provided by the application that invalidates the cookie if command should be provided by the application that invalidates the cookie if the
the user requests this. <classname>TokenBasedRememberMeServices</classname> also user requests this. <classname>TokenBasedRememberMeServices</classname> also
implements Spring Security's <interfacename>LogoutHandler</interfacename> interface implements Spring Security's <interfacename>LogoutHandler</interfacename> interface
so can be used with <classname>LogoutFilter</classname> to have the cookie cleared so can be used with <classname>LogoutFilter</classname> to have the cookie cleared
automatically. </para> automatically. </para>
@ -162,14 +162,18 @@
<section> <section>
<title>PersistentTokenBasedRememberMeServices</title> <title>PersistentTokenBasedRememberMeServices</title>
<para> This class can be used in the same way as <para> This class can be used in the same way as
<classname>TokenBasedRememberMeServices</classname>, but it additionally needs <classname>TokenBasedRememberMeServices</classname>, but it additionally needs to be
to be configured with a <interfacename>PersistentTokenRepository</interfacename> to configured with a <interfacename>PersistentTokenRepository</interfacename> to store
store the tokens. There are two standard implementations. the tokens. There are two standard implementations. <itemizedlist>
<itemizedlist><listitem><para><classname>InMemoryTokenRepositoryImpl</classname> <listitem>
which is intended for testing <para><classname>InMemoryTokenRepositoryImpl</classname> which is intended for
only.</para></listitem><listitem><para><classname>JdbcTokenRepositoryImpl</classname> testing only.</para>
which stores the tokens in a database. </para></listitem></itemizedlist> </listitem>
The database schema is described above in <xref <listitem>
<para><classname>JdbcTokenRepositoryImpl</classname> which stores the tokens in
a database. </para>
</listitem>
</itemizedlist> The database schema is described above in <xref
linkend="remember-me-persistent-token"/>. </para> linkend="remember-me-persistent-token"/>. </para>
</section> </section>
</section> </section>

View File

@ -1,92 +1,84 @@
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="runas"><info><title>Run-As Authentication Replacement</title></info> <chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="runas">
<info>
<title>Run-As Authentication Replacement</title>
</info>
<section xml:id="runas-overview"> <section xml:id="runas-overview">
<info><title>Overview</title></info> <info>
<title>Overview</title>
</info>
<para>The <classname>AbstractSecurityInterceptor</classname> is able to <para>The <classname>AbstractSecurityInterceptor</classname> is able to temporarily replace
temporarily replace the <interfacename>Authentication</interfacename> object in the <interfacename>Authentication</interfacename> object in the
the <interfacename>SecurityContext</interfacename> and <interfacename>SecurityContext</interfacename> and
<classname>SecurityContextHolder</classname> during the secure object <classname>SecurityContextHolder</classname> during the secure object callback phase.
callback phase. This only occurs if the original This only occurs if the original <interfacename>Authentication</interfacename> object
<interfacename>Authentication</interfacename> object was successfully processed by was successfully processed by the <interfacename>AuthenticationManager</interfacename>
the <interfacename>AuthenticationManager</interfacename> and and <interfacename>AccessDecisionManager</interfacename>. The
<interfacename>AccessDecisionManager</interfacename>. The
<literal>RunAsManager</literal> will indicate the replacement <literal>RunAsManager</literal> will indicate the replacement
<interfacename>Authentication</interfacename> object, if any, that should be used <interfacename>Authentication</interfacename> object, if any, that should be used during
during the <literal>SecurityInterceptorCallback</literal>.</para> the <literal>SecurityInterceptorCallback</literal>.</para>
<para>By temporarily replacing the <interfacename>Authentication</interfacename> <para>By temporarily replacing the <interfacename>Authentication</interfacename> object
object during the secure object callback phase, the secured invocation during the secure object callback phase, the secured invocation will be able to call
will be able to call other objects which require different other objects which require different authentication and authorization credentials. It
authentication and authorization credentials. It will also be able to will also be able to perform any internal security checks for specific
perform any internal security checks for specific
<interfacename>GrantedAuthority</interfacename> objects. Because Spring Security <interfacename>GrantedAuthority</interfacename> objects. Because Spring Security
provides a number of helper classes that automatically configure provides a number of helper classes that automatically configure remoting protocols
remoting protocols based on the contents of the based on the contents of the <classname>SecurityContextHolder</classname>, these run-as
<classname>SecurityContextHolder</classname>, these run-as replacements replacements are particularly useful when calling remote web services</para>
are particularly useful when calling remote web services</para>
</section> </section>
<section xml:id="runas-config"> <section xml:id="runas-config">
<info><title>Configuration</title></info> <info>
<title>Configuration</title>
</info>
<para>A <literal>RunAsManager</literal> interface is provided by Spring Security: <para>A <literal>RunAsManager</literal> interface is provided by Spring Security:
<programlisting> <programlisting>
Authentication buildRunAs(Authentication authentication, Object object, Authentication buildRunAs(Authentication authentication, Object object,
List&lt;ConfigAttribute&gt; config); List&lt;ConfigAttribute&gt; config);
boolean supports(ConfigAttribute attribute); boolean supports(ConfigAttribute attribute);
boolean supports(Class clazz); boolean supports(Class clazz);
</programlisting> </programlisting> </para>
</para>
<para>The first method returns the <interfacename>Authentication</interfacename> <para>The first method returns the <interfacename>Authentication</interfacename> object that
object that should replace the existing should replace the existing <interfacename>Authentication</interfacename> object for the
<interfacename>Authentication</interfacename> object for the duration of the duration of the method invocation. If the method returns <literal>null</literal>, it
method invocation. If the method returns <literal>null</literal>, it indicates no replacement should be made. The second method is used by the
indicates no replacement should be made. The second method is used by <classname>AbstractSecurityInterceptor</classname> as part of its startup validation of
the <classname>AbstractSecurityInterceptor</classname> as part of its configuration attributes. The <literal>supports(Class)</literal> method is called by a
startup validation of configuration attributes. The security interceptor implementation to ensure the configured
<literal>supports(Class)</literal> method is called by a security <literal>RunAsManager</literal> supports the type of secure object that the security
interceptor implementation to ensure the configured interceptor will present.</para>
<literal>RunAsManager</literal> supports the type of secure object
that the security interceptor will present.</para>
<para>One concrete implementation of a <literal>RunAsManager</literal> <para>One concrete implementation of a <literal>RunAsManager</literal> is provided with
is provided with Spring Security. The Spring Security. The <literal>RunAsManagerImpl</literal> class returns a replacement
<literal>RunAsManagerImpl</literal> class returns a replacement <literal>RunAsUserToken</literal> if any <literal>ConfigAttribute</literal> starts with
<literal>RunAsUserToken</literal> if any <literal>RUN_AS_</literal>. If any such <literal>ConfigAttribute</literal> is found, the
<literal>ConfigAttribute</literal> starts with replacement <literal>RunAsUserToken</literal> will contain the same principal,
<literal>RUN_AS_</literal>. If any such
<literal>ConfigAttribute</literal> is found, the replacement
<literal>RunAsUserToken</literal> will contain the same principal,
credentials and granted authorities as the original credentials and granted authorities as the original
<interfacename>Authentication</interfacename> object, along with a new <interfacename>Authentication</interfacename> object, along with a new
<literal>GrantedAuthorityImpl</literal> for each <literal>GrantedAuthorityImpl</literal> for each <literal>RUN_AS_</literal>
<literal>RUN_AS_</literal> <literal>ConfigAttribute</literal>. Each <literal>ConfigAttribute</literal>. Each new <literal>GrantedAuthorityImpl</literal>
new <literal>GrantedAuthorityImpl</literal> will be prefixed with will be prefixed with <literal>ROLE_</literal>, followed by the
<literal>ROLE_</literal>, followed by the <literal>RUN_AS</literal> <literal>RUN_AS</literal> <literal>ConfigAttribute</literal>. For example, a
<literal>ConfigAttribute</literal>. For example, a
<literal>RUN_AS_SERVER</literal> will result in the replacement <literal>RUN_AS_SERVER</literal> will result in the replacement
<literal>RunAsUserToken</literal> containing a <literal>RunAsUserToken</literal> containing a <literal>ROLE_RUN_AS_SERVER</literal>
<literal>ROLE_RUN_AS_SERVER</literal> granted authority.</para> granted authority.</para>
<para>The replacement <literal>RunAsUserToken</literal> is just like <para>The replacement <literal>RunAsUserToken</literal> is just like any other
any other <interfacename>Authentication</interfacename> object. It needs to be <interfacename>Authentication</interfacename> object. It needs to be authenticated by
authenticated by the <interfacename>AuthenticationManager</interfacename>, the <interfacename>AuthenticationManager</interfacename>, probably via delegation to a
probably via delegation to a suitable suitable <classname>AuthenticationProvider</classname>. The
<classname>AuthenticationProvider</classname>. The <literal>RunAsImplAuthenticationProvider</literal> performs such authentication. It
<literal>RunAsImplAuthenticationProvider</literal> performs such simply accepts as valid any <literal>RunAsUserToken</literal> presented.</para>
authentication. It simply accepts as valid any
<literal>RunAsUserToken</literal> presented.</para>
<para>To ensure malicious code does not create a <para>To ensure malicious code does not create a <literal>RunAsUserToken</literal> and
<literal>RunAsUserToken</literal> and present it for guaranteed present it for guaranteed acceptance by the
acceptance by the <literal>RunAsImplAuthenticationProvider</literal>, <literal>RunAsImplAuthenticationProvider</literal>, the hash of a key is stored in all
the hash of a key is stored in all generated tokens. The generated tokens. The <literal>RunAsManagerImpl</literal> and
<literal>RunAsManagerImpl</literal> and <literal>RunAsImplAuthenticationProvider</literal> is created in the bean context with
<literal>RunAsImplAuthenticationProvider</literal> is created in the the same key: <programlisting>
bean context with the same key:
<programlisting>
<![CDATA[ <![CDATA[
<bean id="runAsManager" <bean id="runAsManager"
class="org.springframework.security.access.intercept.RunAsManagerImpl"> class="org.springframework.security.access.intercept.RunAsManagerImpl">
@ -97,10 +89,9 @@
class="org.springframework.security.access.intercept.RunAsImplAuthenticationProvider"> class="org.springframework.security.access.intercept.RunAsImplAuthenticationProvider">
<property name="key" value="my_run_as_password"/> <property name="key" value="my_run_as_password"/>
</bean>]]></programlisting></para> </bean>]]></programlisting></para>
<para>By using the same key, each <literal>RunAsUserToken</literal> <para>By using the same key, each <literal>RunAsUserToken</literal> can be validated it was
can be validated it was created by an approved created by an approved <literal>RunAsManagerImpl</literal>. The
<literal>RunAsManagerImpl</literal>. The <literal>RunAsUserToken</literal> is immutable after creation for security
<literal>RunAsUserToken</literal> is immutable after creation for reasons</para>
security reasons</para>
</section> </section>
</chapter> </chapter>

View File

@ -10,22 +10,22 @@
the source as described in <link xlink:href="#get-source">the introduction</link> and it's the source as described in <link xlink:href="#get-source">the introduction</link> and it's
easy to build the project using Maven. There is more information on the project web site at easy to build the project using Maven. There is more information on the project web site at
<link xlink:href="http://www.springsource.org/security/"> <link xlink:href="http://www.springsource.org/security/">
http://www.springsource.org/security/ </link> if you need it. All paths referred to in http://www.springsource.org/security/ </link> if you need it. All paths referred to in this
this chapter are relative to the project source directory. </para> chapter are relative to the project source directory. </para>
<section xml:id="tutorial-sample"> <section xml:id="tutorial-sample">
<title>Tutorial Sample</title> <title>Tutorial Sample</title>
<para> The tutorial sample is a nice basic example to get you started. It uses simple <para> The tutorial sample is a nice basic example to get you started. It uses simple
namespace configuration throughout. The compiled application is included in the namespace configuration throughout. The compiled application is included in the
distribution zip file, ready to be deployed into your web container distribution zip file, ready to be deployed into your web container
(<filename>spring-security-samples-tutorial-3.0.x.war</filename>). The <link (<filename>spring-security-samples-tutorial-3.0.x.war</filename>). The <link
xlink:href="#ns-form-and-basic">form-based</link> authentication mechanism is used xlink:href="#ns-form-and-basic">form-based</link> authentication mechanism is used in
in combination with the commonly-used <link xlink:href="#remember-me">remember-me</link> combination with the commonly-used <link xlink:href="#remember-me">remember-me</link>
authentication provider to automatically remember the login using cookies.</para> authentication provider to automatically remember the login using cookies.</para>
<para>We recommend you start with the tutorial sample, as the XML is minimal and easy to <para>We recommend you start with the tutorial sample, as the XML is minimal and easy to
follow. Most importantly, you can easily add this one XML file (and its corresponding follow. Most importantly, you can easily add this one XML file (and its corresponding
<literal>web.xml</literal> entries) to your existing application. Only when this <literal>web.xml</literal> entries) to your existing application. Only when this basic
basic integration is achieved do we suggest you attempt adding in method authorization integration is achieved do we suggest you attempt adding in method authorization or
or domain object security.</para> domain object security.</para>
</section> </section>
<section xml:id="contacts-sample"> <section xml:id="contacts-sample">
<title>Contacts</title> <title>Contacts</title>
@ -35,11 +35,11 @@
administer a simple database of contacts (the domain objects).</para> administer a simple database of contacts (the domain objects).</para>
<para>To deploy, simply copy the WAR file from Spring Security distribution into your <para>To deploy, simply copy the WAR file from Spring Security distribution into your
containers <literal>webapps</literal> directory. The war should be called containers <literal>webapps</literal> directory. The war should be called
<filename>spring-security-samples-contacts-3.0.x.war</filename> (the appended <filename>spring-security-samples-contacts-3.0.x.war</filename> (the appended version
version number will vary depending on what release you are using). </para> number will vary depending on what release you are using). </para>
<para>After starting your container, check the application can load. Visit <para>After starting your container, check the application can load. Visit
<literal>http://localhost:8080/contacts</literal> (or whichever URL is appropriate <literal>http://localhost:8080/contacts</literal> (or whichever URL is appropriate for
for your web container and the WAR you deployed). </para> your web container and the WAR you deployed). </para>
<para>Next, click "Debug". You will be prompted to authenticate, and a series of usernames <para>Next, click "Debug". You will be prompted to authenticate, and a series of usernames
and passwords are suggested on that page. Simply authenticate with any of these and view and passwords are suggested on that page. Simply authenticate with any of these and view
the resulting page. It should contain a success message similar to the following: the resulting page. It should contain a success message similar to the following:
@ -71,8 +71,8 @@ Success! Your web filters appear to be properly configured!
<para>Once you successfully receive the above message, return to the sample application's <para>Once you successfully receive the above message, return to the sample application's
home page and click "Manage". You can then try out the application. Notice that only the home page and click "Manage". You can then try out the application. Notice that only the
contacts available to the currently logged on user are displayed, and only users with contacts available to the currently logged on user are displayed, and only users with
<literal>ROLE_SUPERVISOR</literal> are granted access to delete their contacts. <literal>ROLE_SUPERVISOR</literal> are granted access to delete their contacts. Behind
Behind the scenes, the <classname>MethodSecurityInterceptor</classname> is securing the the scenes, the <classname>MethodSecurityInterceptor</classname> is securing the
business objects. </para> business objects. </para>
<para>The application allows you to modify the access control lists associated with <para>The application allows you to modify the access control lists associated with
different contacts. Be sure to give this a try and understand how it works by reviewing different contacts. Be sure to give this a try and understand how it works by reviewing
@ -103,12 +103,12 @@ Success! Your web filters appear to be properly configured!
<title>CAS Sample</title> <title>CAS Sample</title>
<para> The CAS sample requires that you run both a CAS server and CAS client. It isn't <para> The CAS sample requires that you run both a CAS server and CAS client. It isn't
included in the distribution so you should check out the project code as described in included in the distribution so you should check out the project code as described in
<link xlink:href="get-source">the introduction</link>. You'll find the relevant <link xlink:href="get-source">the introduction</link>. You'll find the relevant files
files under the <filename>sample/cas</filename> directory. There's also a under the <filename>sample/cas</filename> directory. There's also a
<filename>Readme.txt</filename> file in there which explains how to run both the <filename>Readme.txt</filename> file in there which explains how to run both the server
server and the client directly from the source tree, complete with SSL support. You have and the client directly from the source tree, complete with SSL support. You have to
to download the CAS Server web application (a war file) from the CAS site and drop it download the CAS Server web application (a war file) from the CAS site and drop it into
into the <filename>samples/cas/server</filename> directory. </para> the <filename>samples/cas/server</filename> directory. </para>
</section> </section>
<section xml:id="preauth-sample"> <section xml:id="preauth-sample">
<title>Pre-Authentication Sample</title> <title>Pre-Authentication Sample</title>

View File

@ -7,26 +7,28 @@
<info> <info>
<title>AOP Alliance (MethodInvocation) Security Interceptor</title> <title>AOP Alliance (MethodInvocation) Security Interceptor</title>
</info> </info>
<para> Prior to Spring Security 2.0, securing <classname>MethodInvocation</classname>s needed <para> Prior to Spring Security 2.0, securing <classname>MethodInvocation</classname>s
quite a lot of boiler plate configuration. Now the recommended approach for method security is needed quite a lot of boiler plate configuration. Now the recommended approach for
to use <link xlink:href="#ns-method-security">namespace configuration</link>. This way the method security is to use <link xlink:href="#ns-method-security">namespace
method security infrastructure beans are configured automatically for you so you don't really configuration</link>. This way the method security infrastructure beans are configured
need to know about the implementation classes. We'll just provide a quick overview of the automatically for you so you don't really need to know about the implementation classes.
classes that are involved here. </para> We'll just provide a quick overview of the classes that are involved here. </para>
<para> Method security in enforced using a <classname>MethodSecurityInterceptor</classname>, <para> Method security in enforced using a <classname>MethodSecurityInterceptor</classname>,
which secures <classname>MethodInvocation</classname>s. Depending on the configuration which secures <classname>MethodInvocation</classname>s. Depending on the configuration
approach, an interceptor may be specific to a single bean or shared between multiple beans. approach, an interceptor may be specific to a single bean or shared between multiple
The interceptor uses a <interfacename>MethodSecurityMetadataSource</interfacename> instance to beans. The interceptor uses a
obtain the configuration attributes that apply to a particular method invocation. <interfacename>MethodSecurityMetadataSource</interfacename> instance to obtain the
<classname>MapBasedMethodSecurityMetadataSource</classname> is used to store configuration configuration attributes that apply to a particular method invocation.
attributes keyed by method names (which can be wildcarded) and will be used internally when <classname>MapBasedMethodSecurityMetadataSource</classname> is used to store
the attributes are defined in the application context using the configuration attributes keyed by method names (which can be wildcarded) and will be
used internally when the attributes are defined in the application context using the
<literal>&lt;intercept-methods&gt;</literal> or <literal>&lt;protect-point&gt;</literal> <literal>&lt;intercept-methods&gt;</literal> or <literal>&lt;protect-point&gt;</literal>
elements. Other implementations will be used to handle annotation-based configuration. </para> elements. Other implementations will be used to handle annotation-based configuration. </para>
<section> <section>
<title>Explicit MethodSecurityInterceptor Configuration</title> <title>Explicit MethodSecurityInterceptor Configuration</title>
<para> You can of course configure a <classname>MethodSecurityIterceptor</classname> directly <para> You can of course configure a <classname>MethodSecurityIterceptor</classname>
in your application context for use with one of Spring AOP's proxying mechanisms: <programlisting><![CDATA[ directly in your application context for use with one of Spring AOP's proxying
mechanisms: <programlisting><![CDATA[
<bean id="bankManagerSecurity" class= <bean id="bankManagerSecurity" class=
"org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor"> "org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/> <property name="authenticationManager" ref="authenticationManager"/>
@ -46,19 +48,20 @@
<info> <info>
<title>AspectJ (JoinPoint) Security Interceptor</title> <title>AspectJ (JoinPoint) Security Interceptor</title>
</info> </info>
<para>The AspectJ security interceptor is very similar to the AOP Alliance security interceptor <para>The AspectJ security interceptor is very similar to the AOP Alliance security
discussed in the previous section. Indeed we will only discuss the differences in this interceptor discussed in the previous section. Indeed we will only discuss the
section.</para> differences in this section.</para>
<para>The AspectJ interceptor is named <literal>AspectJSecurityInterceptor</literal>. Unlike the <para>The AspectJ interceptor is named <literal>AspectJSecurityInterceptor</literal>. Unlike
AOP Alliance security interceptor, which relies on the Spring application context to weave in the AOP Alliance security interceptor, which relies on the Spring application context to
the security interceptor via proxying, the <literal>AspectJSecurityInterceptor</literal> is weave in the security interceptor via proxying, the
weaved in via the AspectJ compiler. It would not be uncommon to use both types of security <literal>AspectJSecurityInterceptor</literal> is weaved in via the AspectJ compiler. It
interceptors in the same application, with <literal>AspectJSecurityInterceptor</literal> being would not be uncommon to use both types of security interceptors in the same
used for domain object instance security and the AOP Alliance application, with <literal>AspectJSecurityInterceptor</literal> being used for domain
object instance security and the AOP Alliance
<classname>MethodSecurityInterceptor</classname> being used for services layer <classname>MethodSecurityInterceptor</classname> being used for services layer
security.</para> security.</para>
<para>Let's first consider how the <literal>AspectJSecurityInterceptor</literal> is configured <para>Let's first consider how the <literal>AspectJSecurityInterceptor</literal> is
in the Spring application context:</para> configured in the Spring application context:</para>
<programlisting><![CDATA[ <programlisting><![CDATA[
<bean id="bankManagerSecurity" class= <bean id="bankManagerSecurity" class=
"org.springframework.security.access.intercept.aspectj.AspectJSecurityInterceptor"> "org.springframework.security.access.intercept.aspectj.AspectJSecurityInterceptor">
@ -77,11 +80,11 @@
security interceptor. Indeed the two interceptors can share the same security interceptor. Indeed the two interceptors can share the same
<literal>securityMetadataSource</literal>, as the <literal>securityMetadataSource</literal>, as the
<interfacename>SecurityMetadataSource</interfacename> works with <interfacename>SecurityMetadataSource</interfacename> works with
<literal>java.lang.reflect.Method</literal>s rather than an AOP library-specific class. Of <literal>java.lang.reflect.Method</literal>s rather than an AOP library-specific class.
course, your access decisions have access to the relevant AOP library-specific invocation (ie Of course, your access decisions have access to the relevant AOP library-specific
<classname>MethodInvocation</classname> or <literal>JoinPoint</literal>) and as such can invocation (ie <classname>MethodInvocation</classname> or <literal>JoinPoint</literal>)
consider a range of addition criteria when making access decisions (such as method and as such can consider a range of addition criteria when making access decisions (such
arguments).</para> as method arguments).</para>
<para>Next you'll need to define an AspectJ <literal>aspect</literal>. For example:</para> <para>Next you'll need to define an AspectJ <literal>aspect</literal>. For example:</para>
<programlisting language="java"> <programlisting language="java">
package org.springframework.security.samples.aspectj; package org.springframework.security.samples.aspectj;
@ -127,12 +130,13 @@ public aspect DomainObjectInstanceSecurityAspect implements InitializingBean {
} }
</programlisting> </programlisting>
<para>In the above example, the security interceptor will be applied to every instance of <para>In the above example, the security interceptor will be applied to every instance of
<literal>PersistableEntity</literal>, which is an abstract class not shown (you can use any <literal>PersistableEntity</literal>, which is an abstract class not shown (you can use
other class or <literal>pointcut</literal> expression you like). For those curious, any other class or <literal>pointcut</literal> expression you like). For those curious,
<literal>AspectJCallback</literal> is needed because the <literal>proceed();</literal> <literal>AspectJCallback</literal> is needed because the <literal>proceed();</literal>
statement has special meaning only within an <literal>around()</literal> body. The statement has special meaning only within an <literal>around()</literal> body. The
<literal>AspectJSecurityInterceptor</literal> calls this anonymous <literal>AspectJSecurityInterceptor</literal> calls this anonymous
<literal>AspectJCallback</literal> class when it wants the target object to continue.</para> <literal>AspectJCallback</literal> class when it wants the target object to
continue.</para>
<para>You will need to configure Spring to load the aspect and wire it with the <para>You will need to configure Spring to load the aspect and wire it with the
<literal>AspectJSecurityInterceptor</literal>. A bean declaration which achieves this is <literal>AspectJSecurityInterceptor</literal>. A bean declaration which achieves this is
shown below:</para> shown below:</para>
@ -144,7 +148,7 @@ public aspect DomainObjectInstanceSecurityAspect implements InitializingBean {
</bean>]]> </bean>]]>
</programlisting> </programlisting>
<para>That's it! Now you can create your beans from anywhere within your application, using <para>That's it! Now you can create your beans from anywhere within your application, using
whatever means you think fit (eg <literal>new Person();</literal>) and they will have the whatever means you think fit (eg <literal>new Person();</literal>) and they will have
security interceptor applied.</para> the security interceptor applied.</para>
</section> </section>
</chapter> </chapter>

View File

@ -4,29 +4,29 @@
<title>The Security Filter Chain</title> <title>The Security Filter Chain</title>
</info> </info>
<para>Spring Security's web infrastructure is based entirely on standard servlet filters. It <para>Spring Security's web infrastructure is based entirely on standard servlet filters. It
doesn't use servlets or any other servlet-based frameworks (such as Spring MVC) internally, so doesn't use servlets or any other servlet-based frameworks (such as Spring MVC) internally,
it has no strong links to any particular web technology. It deals in so it has no strong links to any particular web technology. It deals in
<classname>HttpServletRequest</classname>s and <classname>HttpServletResponse</classname>s and <classname>HttpServletRequest</classname>s and <classname>HttpServletResponse</classname>s
doesn't care whether the requests come from a browser, a web service client, an and doesn't care whether the requests come from a browser, a web service client, an
<classname>HttpInvoker</classname> or an AJAX application. </para> <classname>HttpInvoker</classname> or an AJAX application. </para>
<para> Spring Security maintains a filter chain internally where each of the filters has a <para> Spring Security maintains a filter chain internally where each of the filters has a
particular responsibility and filters are added or removed from the configuration depending on particular responsibility and filters are added or removed from the configuration depending
which services are required. The ordering of the filters is important as there are dependencies on which services are required. The ordering of the filters is important as there are
between them. If you have been using <link xlink:href="#ns-config">namespace dependencies between them. If you have been using <link xlink:href="#ns-config">namespace
configuration</link>, then the filters are automatically configured for you and you don't have configuration</link>, then the filters are automatically configured for you and you don't
to define any Spring beans explicitly but here may be times when you want full control over the have to define any Spring beans explicitly but here may be times when you want full control
security filter chain, either because you are using features which aren't supported in the over the security filter chain, either because you are using features which aren't supported
namespace, or you are using your own customized versions of classes.</para> in the namespace, or you are using your own customized versions of classes.</para>
<section xml:id="delegating-filter-proxy"> <section xml:id="delegating-filter-proxy">
<title><classname>DelegatingFilterProxy</classname></title> <title><classname>DelegatingFilterProxy</classname></title>
<para> When using servlet filters, you obviously need to declare them in your <para> When using servlet filters, you obviously need to declare them in your
<filename>web.xml</filename>, or they will be ignored by the servlet container. In Spring <filename>web.xml</filename>, or they will be ignored by the servlet container. In
Security, the filter classes are also Spring beans defined in the application context and thus Spring Security, the filter classes are also Spring beans defined in the application
able to take advantage of Spring's rich dependency-injection facilities and lifecycle context and thus able to take advantage of Spring's rich dependency-injection facilities
interfaces. Spring's <classname>DelegatingFilterProxy</classname> provides the link between and lifecycle interfaces. Spring's <classname>DelegatingFilterProxy</classname> provides
<filename>web.xml</filename> and the application context. </para> the link between <filename>web.xml</filename> and the application context. </para>
<para>When using <classname>DelegatingFilterProxy</classname>, you will see something like this <para>When using <classname>DelegatingFilterProxy</classname>, you will see something like
in the <filename>web.xml</filename> file: <programlisting><![CDATA[ this in the <filename>web.xml</filename> file: <programlisting><![CDATA[
<filter> <filter>
<filter-name>myFilter</filter-name> <filter-name>myFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
@ -37,29 +37,29 @@
<url-pattern>/*</url-pattern> <url-pattern>/*</url-pattern>
</filter-mapping>]]> </filter-mapping>]]>
</programlisting> Notice that the filter is actually a </programlisting> Notice that the filter is actually a
<literal>DelegatingFilterProxy</literal>, and not the class that will actually implement the <literal>DelegatingFilterProxy</literal>, and not the class that will actually implement
logic of the filter. What <classname>DelegatingFilterProxy</classname> does is delegate the the logic of the filter. What <classname>DelegatingFilterProxy</classname> does is
<interfacename>Filter</interfacename>'s methods through to a bean which is obtained from the delegate the <interfacename>Filter</interfacename>'s methods through to a bean which is
Spring application context. This enables the bean to benefit from the Spring web application obtained from the Spring application context. This enables the bean to benefit from the
context lifecycle support and configuration flexibility. The bean must implement Spring web application context lifecycle support and configuration flexibility. The bean
<interfacename>javax.servlet.Filter</interfacename> and it must have the same name as that must implement <interfacename>javax.servlet.Filter</interfacename> and it must have the
in the <literal>filter-name</literal> element. Read the Javadoc for same name as that in the <literal>filter-name</literal> element. Read the Javadoc for
<classname>DelegatingFilterProxy</classname> for more information</para> <classname>DelegatingFilterProxy</classname> for more information</para>
</section> </section>
<section xml:id="filter-chain-proxy"> <section xml:id="filter-chain-proxy">
<title><classname>FilterChainProxy</classname></title> <title><classname>FilterChainProxy</classname></title>
<para> It should now be clear that you can declare each Spring Security filter bean that you <para> It should now be clear that you can declare each Spring Security filter bean that you
require in your application context file and add a corresponding require in your application context file and add a corresponding
<classname>DelegatingFilterProxy</classname> entry to <filename>web.xml</filename> for each <classname>DelegatingFilterProxy</classname> entry to <filename>web.xml</filename> for
filter, making sure that they are ordered correctly. This is a cumbersome approach and each filter, making sure that they are ordered correctly. This is a cumbersome approach
clutters up the <filename>web.xml</filename> file quickly if we have a lot of filters. We and clutters up the <filename>web.xml</filename> file quickly if we have a lot of
would prefer to just add a single entry to <filename>web.xml</filename> and deal entirely with filters. We would prefer to just add a single entry to <filename>web.xml</filename> and
the application context file for managing our web security beans. This is where Spring deal entirely with the application context file for managing our web security beans.
Secuiryt's <classname>FilterChainProxy</classname> comes in. It is wired using a This is where Spring Secuirity's <classname>FilterChainProxy</classname> comes in. It is
<literal>DelegatingFilterProxy</literal>, just like in the example above, but with the wired using a <literal>DelegatingFilterProxy</literal>, just like in the example above,
<literal>filter-name</literal> set to the bean name <quote>filterChainProxy</quote>. The but with the <literal>filter-name</literal> set to the bean name
filter chain is then declared in the application context with the same bean name. Here's an <quote>filterChainProxy</quote>. The filter chain is then declared in the application
example: <programlisting language="xml"><![CDATA[ context with the same bean name. Here's an example: <programlisting language="xml"><![CDATA[
<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy"> <bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
<sec:filter-chain-map path-type="ant"> <sec:filter-chain-map path-type="ant">
<sec:filter-chain pattern="/webServices/**" filters=" <sec:filter-chain pattern="/webServices/**" filters="
@ -75,104 +75,114 @@
</sec:filter-chain-map> </sec:filter-chain-map>
</bean> </bean>
]]> ]]>
</programlisting> The namespace element <literal>filter-chain-map</literal> is used </programlisting> The namespace element <literal>filter-chain-map</literal> is used to set
to set up the security filter chain(s) which are required within the up the security filter chain(s) which are required within the application<footnote>
application<footnote><para>Note that you'll need to include the security namespace in your <para>Note that you'll need to include the security namespace in your application
application context XML file in order to use this syntax.</para></footnote>. It maps a context XML file in order to use this syntax.</para>
particular URL pattern to a chain of filters built up from the bean names specified in the </footnote>. It maps a particular URL pattern to a chain of filters built up from the
<literal>filters</literal> element. Both regular expressions and Ant Paths are supported, bean names specified in the <literal>filters</literal> element. Both regular expressions
and the most specific URIs appear first. At runtime the and Ant Paths are supported, and the most specific URIs appear first. At runtime the
<classname>FilterChainProxy</classname> will locate the first URI pattern that matches the <classname>FilterChainProxy</classname> will locate the first URI pattern that matches
current web request and the list of filter beans specified by the <literal>filters</literal> the current web request and the list of filter beans specified by the
attribute will be applied to that request. The filters will be invoked in the order they are <literal>filters</literal> attribute will be applied to that request. The filters will
defined, so you have complete control over the filter chain which is applied to a particular be invoked in the order they are defined, so you have complete control over the filter
URL.</para> chain which is applied to a particular URL.</para>
<para>You may have noticed we have declared two <para>You may have noticed we have declared two
<classname>SecurityContextPersistenceFilter</classname>s in the filter chain <classname>SecurityContextPersistenceFilter</classname>s in the filter chain
(<literal>ASC</literal> is short for <literal>allowSessionCreation</literal>, a property of (<literal>ASC</literal> is short for <literal>allowSessionCreation</literal>, a property
<classname>SecurityContextPersistenceFilter</classname>). As web services will never present of <classname>SecurityContextPersistenceFilter</classname>). As web services will never
a <literal>jsessionid</literal> on future requests, creating <literal>HttpSession</literal>s present a <literal>jsessionid</literal> on future requests, creating
for such user agents would be wasteful. If you had a high-volume application which required <literal>HttpSession</literal>s for such user agents would be wasteful. If you had a
maximum scalability, we recommend you use the approach shown above. For smaller applications, high-volume application which required maximum scalability, we recommend you use the
using a single <classname>SecurityContextPersistenceFilter</classname> (with its default approach shown above. For smaller applications, using a single
<classname>SecurityContextPersistenceFilter</classname> (with its default
<literal>allowSessionCreation</literal> as <literal>true</literal>) would likely be <literal>allowSessionCreation</literal> as <literal>true</literal>) would likely be
sufficient.</para> sufficient.</para>
<para>In relation to lifecycle issues, the <classname>FilterChainProxy</classname> will always
delegate <methodname>init(FilterConfig)</methodname> and <methodname>destroy()</methodname>
methods through to the underlaying <interfacename>Filter</interfacename>s if such methods are
called against <classname>FilterChainProxy</classname> itself. In this case,
<classname>FilterChainProxy</classname> guarantees to only initialize and destroy each
<literal>Filter</literal> bean once, no matter how many times it is declared in the filter
chain(s). You control the overall choice as to whether these methods are called or not via the
<literal>targetFilterLifecycle</literal> initialization parameter of
<literal>DelegatingFilterProxy</literal>. By default this property is
<literal>false</literal> and servlet container lifecycle invocations are not delegated
through <literal>DelegatingFilterProxy</literal>.</para>
<para> When we looked at how to set up web security using <link xlink:href="#ns-web-xml" <para> When we looked at how to set up web security using <link xlink:href="#ns-web-xml"
>namespace configuration</link>, we used a <literal>DelegatingFilterProxy</literal> with the >namespace configuration</link>, we used a <literal>DelegatingFilterProxy</literal> with
name <quote>springSecurityFilterChain</quote>. You should now be able to see that this is the the name <quote>springSecurityFilterChain</quote>. You should now be able to see that
name of the <classname>FilterChainProxy</classname> which is created by the namespace. </para> this is the name of the <classname>FilterChainProxy</classname> which is created by the
namespace. </para>
<section> <section>
<title>Bypassing the Filter Chain</title> <title>Bypassing the Filter Chain</title>
<para> As with the namespace, you can use the attribute <literal>filters = "none"</literal> as <para> As with the namespace, you can use the attribute <literal>filters =
an alternative to supplying a filter bean list. This will omit the request pattern from the "none"</literal> as an alternative to supplying a filter bean list. This will omit
security filter chain entirely. Note that anything matching this path will then have no the request pattern from the security filter chain entirely. Note that anything
authentication or authorization services applied and will be freely accessible. If you want matching this path will then have no authentication or authorization services
to make use of the contents of the <classname>SecurityContext</classname> contents during a applied and will be freely accessible. If you want to make use of the contents of
request, then it must have passed through the security filter chain. Otherwise the the <classname>SecurityContext</classname> contents during a request, then it must
<classname>SecurityContextHolder</classname> will not have been populated and the contents have passed through the security filter chain. Otherwise the
will be null.</para> <classname>SecurityContextHolder</classname> will not have been populated and the
contents will be null.</para>
</section> </section>
</section> </section>
<section> <section>
<title>Filter Ordering</title> <title>Filter Ordering</title>
<para>The order that filters are defined in the chain is very important. Irrespective of which <para>The order that filters are defined in the chain is very important. Irrespective of
filters you are actually using, the order should be as follows: which filters you are actually using, the order should be as follows: <orderedlist>
<orderedlist><listitem><para><classname>ChannelProcessingFilter</classname>, because <listitem>
it might need to redirect to a different <para><classname>ChannelProcessingFilter</classname>, because it might need to
protocol</para></listitem><listitem><para><classname>ConcurrentSessionFilter</classname>, redirect to a different protocol</para>
because it doesn't use any <classname>SecurityContextHolder</classname> functionality </listitem>
but needs to update the <interfacename>SessionRegistry</interfacename> to reflect <listitem>
ongoing requests from the <para><classname>ConcurrentSessionFilter</classname>, because it doesn't use any
principal</para></listitem><listitem><para><classname>SecurityContextPersistenceFilter</classname>, <classname>SecurityContextHolder</classname> functionality but needs to update
so a <interfacename>SecurityContext</interfacename> can be set up in the the <interfacename>SessionRegistry</interfacename> to reflect ongoing requests
<classname>SecurityContextHolder</classname> at the beginning of a web request, and from the principal</para>
any changes to the <interfacename>SecurityContext</interfacename> can be copied to the </listitem>
<literal>HttpSession</literal> when the web request ends (ready for use with the next <listitem>
web request)</para></listitem><listitem><para>Authentication processing mechanisms - <para><classname>SecurityContextPersistenceFilter</classname>, so a
<interfacename>SecurityContext</interfacename> can be set up in the
<classname>SecurityContextHolder</classname> at the beginning of a web request,
and any changes to the <interfacename>SecurityContext</interfacename> can be
copied to the <literal>HttpSession</literal> when the web request ends (ready
for use with the next web request)</para>
</listitem>
<listitem>
<para>Authentication processing mechanisms -
<classname>UsernamePasswordAuthenticationFilter</classname>, <classname>UsernamePasswordAuthenticationFilter</classname>,
<classname>CasAuthenticationFilter</classname>, <classname>CasAuthenticationFilter</classname>,
<classname>BasicAuthenticationFilter</classname> etc - so that the <classname>BasicAuthenticationFilter</classname> etc - so that the
<classname>SecurityContextHolder</classname> can be modified to contain a valid <classname>SecurityContextHolder</classname> can be modified to contain a valid
<interfacename>Authentication</interfacename> request <interfacename>Authentication</interfacename> request token</para>
token</para></listitem><listitem><para>The </listitem>
<literal>SecurityContextHolderAwareRequestFilter</literal>, if you are using it to <listitem>
install a Spring Security aware <literal>HttpServletRequestWrapper</literal> into your <para>The <literal>SecurityContextHolderAwareRequestFilter</literal>, if you are
servlet using it to install a Spring Security aware
container</para></listitem><listitem><para><classname>RememberMeAuthenticationFilter</classname>, <literal>HttpServletRequestWrapper</literal> into your servlet container</para>
so that if no earlier authentication processing mechanism updated the </listitem>
<classname>SecurityContextHolder</classname>, and the request presents a cookie that <listitem>
enables remember-me services to take place, a suitable remembered <para><classname>RememberMeAuthenticationFilter</classname>, so that if no earlier
<interfacename>Authentication</interfacename> object will be put authentication processing mechanism updated the
there</para></listitem><listitem><para><classname>AnonymousAuthenticationFilter</classname>, <classname>SecurityContextHolder</classname>, and the request presents a cookie
so that if no earlier authentication processing mechanism updated the that enables remember-me services to take place, a suitable remembered
<interfacename>Authentication</interfacename> object will be put there</para>
</listitem>
<listitem>
<para><classname>AnonymousAuthenticationFilter</classname>, so that if no earlier
authentication processing mechanism updated the
<classname>SecurityContextHolder</classname>, an anonymous <classname>SecurityContextHolder</classname>, an anonymous
<interfacename>Authentication</interfacename> object will be put <interfacename>Authentication</interfacename> object will be put there</para>
there</para></listitem><listitem><para><classname>ExceptionTranslationFilter</classname>, </listitem>
to catch any Spring Security exceptions so that either an HTTP error response can be <listitem>
returned or an appropriate <interfacename>AuthenticationEntryPoint</interfacename> can <para><classname>ExceptionTranslationFilter</classname>, to catch any Spring
be Security exceptions so that either an HTTP error response can be returned or an
launched</para></listitem><listitem><para><classname>FilterSecurityInterceptor</classname>, appropriate <interfacename>AuthenticationEntryPoint</interfacename> can be
to protect web URIs and raise exceptions when access is launched</para>
denied</para></listitem></orderedlist></para> </listitem>
<listitem>
<para><classname>FilterSecurityInterceptor</classname>, to protect web URIs and
raise exceptions when access is denied</para>
</listitem>
</orderedlist></para>
</section> </section>
<section> <section>
<title>Use with other Filter-Based Frameworks</title> <title>Use with other Filter-Based Frameworks</title>
<para>If you're using some other framework that is also filter-based, then you need to make sure <para>If you're using some other framework that is also filter-based, then you need to make
that the Spring Security filters come first. This enables the sure that the Spring Security filters come first. This enables the
<classname>SecurityContextHolder</classname> to be populated in time for use by the other <classname>SecurityContextHolder</classname> to be populated in time for use by the
filters. Examples are the use of SiteMesh to decorate your web pages or a web framework like other filters. Examples are the use of SiteMesh to decorate your web pages or a web
Wicket which uses a filter to handle its requests. </para> framework like Wicket which uses a filter to handle its requests. </para>
</section> </section>
<!-- <!--
<section xml:id="taglib"> <section xml:id="taglib">

View File

@ -6,38 +6,41 @@
<para>HTTP session related functonality is handled by a combination of the <para>HTTP session related functonality is handled by a combination of the
<classname>SessionManagementFilter</classname> and the <classname>SessionManagementFilter</classname> and the
<interfacename>SessionAuthenticationStrategy</interfacename> interface, which the filter <interfacename>SessionAuthenticationStrategy</interfacename> interface, which the filter
delegates to. Typical usage includes session-fixation protection attack prevention, detection of delegates to. Typical usage includes session-fixation protection attack prevention,
session timeouts and restrictions on how many sessions an authenticated user may have open detection of session timeouts and restrictions on how many sessions an authenticated user
concurrently.</para> may have open concurrently.</para>
<section> <section>
<title>SessionManagementFilter</title> <title>SessionManagementFilter</title>
<para>The <classname>SessionManagementFilter</classname> checks the contents of the <para>The <classname>SessionManagementFilter</classname> checks the contents of the
<interfacename>SecurityContextRepository</interfacename> against the current contents of the <interfacename>SecurityContextRepository</interfacename> against the current contents of
<classname>SecurityContextHolder</classname> to determine whether a user has been the <classname>SecurityContextHolder</classname> to determine whether a user has been
authenticated during the current request, typically by a non-interactive authentication authenticated during the current request, typically by a non-interactive authentication
mechanism, such as pre-authentication or remember-me <footnote><para>Authentication by mechanism, such as pre-authentication or remember-me <footnote>
mechanisms which perform a redirect after authenticating (such as form-login) will not be <para>Authentication by mechanisms which perform a redirect after authenticating (such
detected by <classname>SessionManagementFilter</classname>, as the filter will not be as form-login) will not be detected by
invoked during the authenticating request. Session-management functionality has to be <classname>SessionManagementFilter</classname>, as the filter will not be invoked
handled separately in these cases. </para></footnote>. If the repository contains a during the authenticating request. Session-management functionality has to be
security context, the filter does nothing. If it doesn't, and the thread-local handled separately in these cases. </para>
<interfacename>SecurityContext</interfacename> contains a (non-anonymous) </footnote>. If the repository contains a security context, the filter does nothing. If
<interfacename>Authentication</interfacename> object, the filter assumes they have been it doesn't, and the thread-local <interfacename>SecurityContext</interfacename> contains
authenticated by a previous filter in the stack. It will then invoke the configured a (non-anonymous) <interfacename>Authentication</interfacename> object, the filter
assumes they have been authenticated by a previous filter in the stack. It will then
invoke the configured
<interfacename>SessionAuthenticationStrategy</interfacename>.</para> <interfacename>SessionAuthenticationStrategy</interfacename>.</para>
<para>If the user is not currently authenticated, the filter will check whether an invalid <para>If the user is not currently authenticated, the filter will check whether an invalid
session ID has been requested (because of a timeout, for example) and will redirect to the session ID has been requested (because of a timeout, for example) and will redirect to
configured <literal>invalidSessionUrl</literal> if set. The easiest way to configure this is the configured <literal>invalidSessionUrl</literal> if set. The easiest way to configure
through the namespace, <link xlink:href="#ns-session-mgmt">as described earlier</link>.</para> this is through the namespace, <link xlink:href="#ns-session-mgmt">as described
earlier</link>.</para>
</section> </section>
<section> <section>
<title><interfacename>SessionAuthenticationStrategy</interfacename></title> <title><interfacename>SessionAuthenticationStrategy</interfacename></title>
<para> <para> <interfacename>SessionAuthenticationStrategy</interfacename> is used by both
<interfacename>SessionAuthenticationStrategy</interfacename> is used by both
<classname>SessionManagementFilter</classname> and <classname>SessionManagementFilter</classname> and
<classname>AbstractAuthenticationProcessingFilter</classname>, so if you are using a <classname>AbstractAuthenticationProcessingFilter</classname>, so if you are using a
customized form-login class, for example, you will need to inject it into both of these. In customized form-login class, for example, you will need to inject it into both of these.
this case, a typical configuration, combining the namespace and custom beans might look like this:<programlisting><![CDATA[ In this case, a typical configuration, combining the namespace and custom beans might
look like this:<programlisting><![CDATA[
<http> <http>
<custom-filter position="FORM_LOGIN_FILTER" ref="myAuthFilter" /> <custom-filter position="FORM_LOGIN_FILTER" ref="myAuthFilter" />
<session-management session-authentication-strategy-ref="sas"/> <session-management session-authentication-strategy-ref="sas"/>
@ -60,27 +63,31 @@
<section xml:id="concurrent-sessions"> <section xml:id="concurrent-sessions">
<title>Concurrency Control</title> <title>Concurrency Control</title>
<para>Spring Security is able to prevent a principal from concurrently authenticating to the <para>Spring Security is able to prevent a principal from concurrently authenticating to the
same application more than a specified number of times. Many ISVs take advantage of this to same application more than a specified number of times. Many ISVs take advantage of this
enforce licensing, whilst network administrators like this feature because it helps prevent to enforce licensing, whilst network administrators like this feature because it helps
people from sharing login names. You can, for example, stop user <quote>Batman</quote> from prevent people from sharing login names. You can, for example, stop user
logging onto the web application from two different sessions. You can either expire their <quote>Batman</quote> from logging onto the web application from two different sessions.
previous login or you can report an error when they try to log in again, preventing the second You can either expire their previous login or you can report an error when they try to
login. Note that if you are using the second approach, a user who has not explicitly logged log in again, preventing the second login. Note that if you are using the second
out (but who has just closed their browser, for example) will not be able to log in again approach, a user who has not explicitly logged out (but who has just closed their
until their original session expires.</para> browser, for example) will not be able to log in again until their original session
<para>Concurrency control is supported by the namespace, so please check the earlier namespace expires.</para>
chapter for the simplest configuration. Sometimes you need to customize things though. </para> <para>Concurrency control is supported by the namespace, so please check the earlier
namespace chapter for the simplest configuration. Sometimes you need to customize things
though. </para>
<para>The implementation uses a specialized version of <para>The implementation uses a specialized version of
<interfacename>SessionAuthenticationStrategy</interfacename>, called <interfacename>SessionAuthenticationStrategy</interfacename>, called
<classname>ConcurrentSessionControlStrategy</classname>. <note><para>Previously the <classname>ConcurrentSessionControlStrategy</classname>. <note>
concurrent authentication check was made by the <classname>ProviderManager</classname>, <para>Previously the concurrent authentication check was made by the
which could be injected with a <literal>ConcurrentSessionController</literal>. The latter <classname>ProviderManager</classname>, which could be injected with a
would check if the user was attempting to exceed the number of permitted sessions. <literal>ConcurrentSessionController</literal>. The latter would check if the user
However, this approach required that an HTTP session be created in advance, which is was attempting to exceed the number of permitted sessions. However, this approach
undesirable. In Spring Security 3, the user is first authenticated by the required that an HTTP session be created in advance, which is undesirable. In Spring
Security 3, the user is first authenticated by the
<interfacename>AuthenticationManager</interfacename> and once they are successfully <interfacename>AuthenticationManager</interfacename> and once they are successfully
authenticated, a session is created and the check is made whether they are allowed to have authenticated, a session is created and the check is made whether they are allowed
another session open.</para></note></para> to have another session open.</para>
</note></para>
<para>To use concurrent session support, you'll need to add the following to <para>To use concurrent session support, you'll need to add the following to
<literal>web.xml</literal>: <programlisting><![CDATA[ <literal>web.xml</literal>: <programlisting><![CDATA[
<listener> <listener>
@ -89,13 +96,14 @@
</listener-class> </listener-class>
</listener> ]]> </listener> ]]>
</programlisting></para> </programlisting></para>
<para>In addition, you will need to add the <literal>ConcurrentSessionFilter</literal> to your <para>In addition, you will need to add the <literal>ConcurrentSessionFilter</literal> to
<classname>FilterChainProxy</classname>. The <classname>ConcurrentSessionFilter</classname> your <classname>FilterChainProxy</classname>. The
requires two properties, <literal>sessionRegistry</literal>, which generally points to an <classname>ConcurrentSessionFilter</classname> requires two properties,
instance of <classname>SessionRegistryImpl</classname>, and <literal>expiredUrl</literal>, which <literal>sessionRegistry</literal>, which generally points to an instance of
points to the page to display when a session has expired. A configuration using the namespace <classname>SessionRegistryImpl</classname>, and <literal>expiredUrl</literal>, which
to create the <classname>FilterChainProxy</classname> and other default beans might look like points to the page to display when a session has expired. A configuration using the
this: <programlisting><![CDATA[ namespace to create the <classname>FilterChainProxy</classname> and other default beans
might look like this: <programlisting><![CDATA[
<http> <http>
<custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" /> <custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
<custom-filter position="FORM_LOGIN_FILTER" ref="myAuthFilter" /> <custom-filter position="FORM_LOGIN_FILTER" ref="myAuthFilter" />
@ -127,10 +135,10 @@
</programlisting></para> </programlisting></para>
<para>Adding the listener to <filename>web.xml</filename> causes an <para>Adding the listener to <filename>web.xml</filename> causes an
<literal>ApplicationEvent</literal> to be published to the Spring <literal>ApplicationEvent</literal> to be published to the Spring
<literal>ApplicationContext</literal> every time a <literal>HttpSession</literal> commences <literal>ApplicationContext</literal> every time a <literal>HttpSession</literal>
or terminates. This is critical, as it allows the <classname>SessionRegistryImpl</classname> commences or terminates. This is critical, as it allows the
to be notified when a session ends. Without it, a user will never be able to log back in again <classname>SessionRegistryImpl</classname> to be notified when a session ends. Without
once they have exceeded their session allowance, even if they log out of another session or it it, a user will never be able to log back in again once they have exceeded their session
times out.</para> allowance, even if they log out of another session or it times out.</para>
</section> </section>
</chapter> </chapter>

View File

@ -1,7 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<book version="5.0" xml:id="spring-security-reference-guide" xmlns="http://docbook.org/ns/docbook" <book version="5.0" xml:id="spring-security-reference-guide" xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xi="http://www.w3.org/2001/XInclude"> xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xi="http://www.w3.org/2001/XInclude">
<info><title>Spring Security</title><subtitle>Reference Documentation</subtitle><authorgroup> <info>
<title>Spring Security</title>
<subtitle>Reference Documentation</subtitle>
<authorgroup>
<author> <author>
<personname>Ben Alex</personname> <personname>Ben Alex</personname>
</author> </author>
@ -16,72 +19,78 @@
<preface xml:id="preface"> <preface xml:id="preface">
<title>Preface</title> <title>Preface</title>
<para>Spring Security provides a comprehensive security solution for J2EE-based enterprise <para>Spring Security provides a comprehensive security solution for J2EE-based enterprise
software applications. As you will discover as you venture through this reference guide, we software applications. As you will discover as you venture through this reference guide,
have tried to provide you a useful and highly configurable security system.</para> we have tried to provide you a useful and highly configurable security system.</para>
<para>Security is an ever-moving target, and it's important to pursue a comprehensive, <para>Security is an ever-moving target, and it's important to pursue a comprehensive,
system-wide approach. In security circles we encourage you to adopt "layers of security", so system-wide approach. In security circles we encourage you to adopt "layers of
that each layer tries to be as secure as possible in its own right, with successive layers security", so that each layer tries to be as secure as possible in its own right, with
providing additional security. The "tighter" the security of each layer, the more robust and successive layers providing additional security. The "tighter" the security of each
safe your application will be. At the bottom level you'll need to deal with issues such as layer, the more robust and safe your application will be. At the bottom level you'll
transport security and system identification, in order to mitigate man-in-the-middle attacks. need to deal with issues such as transport security and system identification, in order
Next you'll generally utilise firewalls, perhaps with VPNs or IP security to ensure only to mitigate man-in-the-middle attacks. Next you'll generally utilise firewalls, perhaps
authorised systems can attempt to connect. In corporate environments you may deploy a DMZ to with VPNs or IP security to ensure only authorised systems can attempt to connect. In
separate public-facing servers from backend database and application servers. Your operating corporate environments you may deploy a DMZ to separate public-facing servers from
system will also play a critical part, addressing issues such as running processes as backend database and application servers. Your operating system will also play a
non-privileged users and maximising file system security. An operating system will usually critical part, addressing issues such as running processes as non-privileged users and
also be configured with its own firewall. Hopefully somewhere along the way you'll be trying maximising file system security. An operating system will usually also be configured
to prevent denial of service and brute force attacks against the system. An intrusion with its own firewall. Hopefully somewhere along the way you'll be trying to prevent
detection system will also be especially useful for monitoring and responding to attacks, with denial of service and brute force attacks against the system. An intrusion detection
such systems able to take protective action such as blocking offending TCP/IP addresses in system will also be especially useful for monitoring and responding to attacks, with
real-time. Moving to the higher layers, your Java Virtual Machine will hopefully be configured such systems able to take protective action such as blocking offending TCP/IP addresses
to minimize the permissions granted to different Java types, and then your application will in real-time. Moving to the higher layers, your Java Virtual Machine will hopefully be
add its own problem domain-specific security configuration. Spring Security makes this latter configured to minimize the permissions granted to different Java types, and then your
area - application security - much easier. </para> application will add its own problem domain-specific security configuration. Spring
<para>Of course, you will need to properly address all security layers mentioned above, together Security makes this latter area - application security - much easier. </para>
with managerial factors that encompass every layer. A non-exhaustive list of such managerial <para>Of course, you will need to properly address all security layers mentioned above,
factors would include security bulletin monitoring, patching, personnel vetting, audits, together with managerial factors that encompass every layer. A non-exhaustive list of
change control, engineering management systems, data backup, disaster recovery, performance such managerial factors would include security bulletin monitoring, patching, personnel
benchmarking, load monitoring, centralised logging, incident response procedures etc.</para> vetting, audits, change control, engineering management systems, data backup, disaster
<para>With Spring Security being focused on helping you with the enterprise application security recovery, performance benchmarking, load monitoring, centralised logging, incident
layer, you will find that there are as many different requirements as there are business response procedures etc.</para>
problem domains. A banking application has different needs from an ecommerce application. An <para>With Spring Security being focused on helping you with the enterprise application
ecommerce application has different needs from a corporate sales force automation tool. These security layer, you will find that there are as many different requirements as there are
custom requirements make application security interesting, challenging and rewarding. </para> business problem domains. A banking application has different needs from an ecommerce
<para>Please read <xref linkend="getting-started"/>, in its entirety to begin with. This will application. An ecommerce application has different needs from a corporate sales force
introduce you to the framework and the namespace-based configuration system with which you can automation tool. These custom requirements make application security interesting,
get up and running quite quickly. To get more of an understanding of how Spring Security challenging and rewarding. </para>
works, and some of the classes you might need to use, you should then read <xref <para>Please read <xref linkend="getting-started"/>, in its entirety to begin with. This
linkend="overall-architecture"/>. The remaining parts of this guide are structured in a more will introduce you to the framework and the namespace-based configuration system with
traditional reference style, designed to be read on an as-required basis. We'd also recommend which you can get up and running quite quickly. To get more of an understanding of how
that you read up as much as possible on application security issues in general. Spring Spring Security works, and some of the classes you might need to use, you should then
Security is not a panacea which will solve all security issues. It is important that the read <xref linkend="overall-architecture"/>. The remaining parts of this guide are
application is designed with security in mind from the start. Attempting to retrofit it is not structured in a more traditional reference style, designed to be read on an as-required
a good idea. In particular, if you are building a web application, you should be aware of the basis. We'd also recommend that you read up as much as possible on application security
many potential vulnerabilities such as cross-site scripting, request-forgery and issues in general. Spring Security is not a panacea which will solve all security
session-hijacking which you should be taking into account from the start. The OWASP web site issues. It is important that the application is designed with security in mind from the
(http://www.owasp.org/) maintains a top ten list of web application vulnerabilities as well as start. Attempting to retrofit it is not a good idea. In particular, if you are building
a lot of useful reference information. </para> a web application, you should be aware of the many potential vulnerabilities such as
<para>We hope that you find this reference guide useful, and we welcome your feedback and <link cross-site scripting, request-forgery and session-hijacking which you should be taking
xlink:href="#jira">suggestions</link>. </para> into account from the start. The OWASP web site (http://www.owasp.org/) maintains a top
<para>Finally, welcome to the Spring Security <link xlink:href="#community">community</link>. ten list of web application vulnerabilities as well as a lot of useful reference
</para> information. </para>
<para>We hope that you find this reference guide useful, and we welcome your feedback and
<link xlink:href="#jira">suggestions</link>. </para>
<para>Finally, welcome to the Spring Security <link xlink:href="#community"
>community</link>. </para>
</preface> </preface>
<part xml:id="getting-started"> <part xml:id="getting-started">
<title>Getting Started</title> <title>Getting Started</title>
<partintro> <partintro>
<para>The later parts of this guide provide an in-depth discussion of the framework <para>The later parts of this guide provide an in-depth discussion of the framework
architecture and implementation classes, which you need to understand if you want to do any architecture and implementation classes, which you need to understand if you want to
serious customization. In this part, we'll introduce Spring Security 3.0, give a brief do any serious customization. In this part, we'll introduce Spring Security 3.0,
overview of the project's history and take a slightly gentler look at how to get started give a brief overview of the project's history and take a slightly gentler look at
using the framework. In particular, we'll look at namespace configuration which provides a how to get started using the framework. In particular, we'll look at namespace
much simpler way of securing your application compared to the traditional Spring bean configuration which provides a much simpler way of securing your application
approach where you have to wire up all the implementation classes individually. </para> compared to the traditional Spring bean approach where you have to wire up all the
<para> We'll also take a look at the sample applications that are available. It's worth trying implementation classes individually. </para>
to run these and experimenting with them a bit even before you read the later sections - you <para> We'll also take a look at the sample applications that are available. It's worth
can dip back into them as your understanding of the framework increases. Please also check trying to run these and experimenting with them a bit even before you read the later
out the <link xlink:href="http://static.springsource.org/spring-security/site/index.html" sections - you can dip back into them as your understanding of the framework
>project website</link> as it has useful information on building the project, plus links increases. Please also check out the <link
to articles, videos and tutorials. </para> xlink:href="http://static.springsource.org/spring-security/site/index.html"
>project website</link> as it has useful information on building the project,
plus links to articles, videos and tutorials. </para>
</partintro> </partintro>
<xi:include href="introduction.xml"/> <xi:include href="introduction.xml"/>
<xi:include href="namespace-config.xml"/> <xi:include href="namespace-config.xml"/>
@ -91,13 +100,13 @@
<part xml:id="overall-architecture"> <part xml:id="overall-architecture">
<title>Architecture and Implementation</title> <title>Architecture and Implementation</title>
<partintro> <partintro>
<para>Once you are familiar with setting up and running some namespace-configuration based <para>Once you are familiar with setting up and running some namespace-configuration
applications, you may wish to develop more of an understanding of how the framework actually based applications, you may wish to develop more of an understanding of how the
works behind the namespace facade. Like most software, Spring Security has certain central framework actually works behind the namespace facade. Like most software, Spring
interfaces, classes and conceptual abstractions that are commonly used throughout the Security has certain central interfaces, classes and conceptual abstractions that
framework. In this part of the reference guide we will look at some of these and see how are commonly used throughout the framework. In this part of the reference guide we
they work together to support authentication and access-control within Spring will look at some of these and see how they work together to support authentication
Security.</para> and access-control within Spring Security.</para>
</partintro> </partintro>
<xi:include href="technical-overview.xml"/> <xi:include href="technical-overview.xml"/>
<xi:include href="core-services.xml"/> <xi:include href="core-services.xml"/>
@ -105,13 +114,14 @@
<part xml:id="web-app-security"> <part xml:id="web-app-security">
<title>Web Application Security</title> <title>Web Application Security</title>
<partintro> <partintro>
<para> Most Spring Security users will be using the framework in applications which make user <para> Most Spring Security users will be using the framework in applications which make
of HTTP and the Servlet API. In this part, we'll take a look at how Spring Security provides user of HTTP and the Servlet API. In this part, we'll take a look at how Spring
authentication and access-control features for the web layer of an application. We'll look Security provides authentication and access-control features for the web layer of an
behind the facade of the namespace and see which classes and interfaces are actually application. We'll look behind the facade of the namespace and see which classes and
assembled to provide web-layer security. In some situations it is necessary to use interfaces are actually assembled to provide web-layer security. In some situations
traditional bean configuration to provide full control over the configuration, so we'll also it is necessary to use traditional bean configuration to provide full control over
see how to configure these classes directly without the namespace.</para> the configuration, so we'll also see how to configure these classes directly without
the namespace.</para>
</partintro> </partintro>
<xi:include href="security-filter-chain.xml"/> <xi:include href="security-filter-chain.xml"/>
<xi:include href="core-filters.xml"/> <xi:include href="core-filters.xml"/>
@ -148,16 +158,16 @@
<part xml:id="authorization"> <part xml:id="authorization">
<title>Authorization</title> <title>Authorization</title>
<partintro> <partintro>
<para>The advanced authorization capabilities within Spring Security represent one of the most <para>The advanced authorization capabilities within Spring Security represent one of
compelling reasons for its popularity. Irrespective of how you choose to authenticate - the most compelling reasons for its popularity. Irrespective of how you choose to
whether using a Spring Security-provided mechanism and provider, or integrating with a authenticate - whether using a Spring Security-provided mechanism and provider, or
container or other non-Spring Security authentication authority - you will find the integrating with a container or other non-Spring Security authentication authority -
authorization services can be used within your application in a consistent and simple you will find the authorization services can be used within your application in a
way.</para> consistent and simple way.</para>
<para>In this part we'll explore the different <para>In this part we'll explore the different
<classname>AbstractSecurityInterceptor</classname> implementations, which were introduced <classname>AbstractSecurityInterceptor</classname> implementations, which were
in Part I. We then move on to explore how to fine-tune authorization through use of domain introduced in Part I. We then move on to explore how to fine-tune authorization
access control lists.</para> through use of domain access control lists.</para>
</partintro> </partintro>
<xi:include href="authorization-common.xml"/> <xi:include href="authorization-common.xml"/>
<xi:include href="secured-objects.xml"/> <xi:include href="secured-objects.xml"/>
@ -169,8 +179,9 @@
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 features which require a knowledge of previous chapters as well <para> In this part we cover features which require a knowledge of previous chapters as
as some of the more advanced and less-commonly used features of the framework.</para> well as 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"/>

View File

@ -17,12 +17,12 @@
<para>The legacy options from Spring Security 2.0 are also supported, but <para>The legacy options from Spring Security 2.0 are also supported, but
discouraged.</para> discouraged.</para>
</footnote>. The first approach uses a <link xlink:href="el-access-we">web-security </footnote>. The first approach uses a <link xlink:href="el-access-we">web-security
expression</link>, specified in the <literal>access</literal> attribute of the tag. expression</link>, specified in the <literal>access</literal> attribute of the tag. The
The expression evaluation will be delegated to the expression evaluation will be delegated to the
<interfacename>WebSecurityExpressionHandler</interfacename> defined in the <interfacename>WebSecurityExpressionHandler</interfacename> defined in the application
application context (you should have web expressions enabled in your context (you should have web expressions enabled in your <literal>&lt;http></literal>
<literal>&lt;http></literal> namespace configuration to make sure this service is namespace configuration to make sure this service is available). So, for example, you
available). So, for example, you might might
have<programlisting>&lt;sec:authorize access="hasRole('supervisor')"> have<programlisting>&lt;sec:authorize access="hasRole('supervisor')">
This content will only be visible to users who have This content will only be visible to users who have
@ -58,13 +58,13 @@ This content will only be visible to users who are authorized to send requests t
the JSP. So, for example, if the <literal>principal</literal> property of the the JSP. So, for example, if the <literal>principal</literal> property of the
<interfacename>Authentication</interfacename> is an instance of Spring Security's <interfacename>Authentication</interfacename> is an instance of Spring Security's
<interfacename>UserDetails</interfacename> object, then using <interfacename>UserDetails</interfacename> object, then using
<literal>&lt;sec:authentication property="principal.username" /></literal> will <literal>&lt;sec:authentication property="principal.username" /></literal> will render
render the name of the current user.</para> the name of the current user.</para>
<para>Of course, it isn't necessary to use JSP tags for this kind of thing and some people <para>Of course, it isn't necessary to use JSP tags for this kind of thing and some people
prefer to keep as little logic as possible in the view. You can access the prefer to keep as little logic as possible in the view. You can access the
<interfacename>Authentication</interfacename> object in your MVC controller (by <interfacename>Authentication</interfacename> object in your MVC controller (by calling
calling <code>SecurityContextHolder.getContext().getAuthentication()</code>) and add the <code>SecurityContextHolder.getContext().getAuthentication()</code>) and add the data
data directly to your model for rendering by the view.</para> directly to your model for rendering by the view.</para>
</section> </section>
<section> <section>
<title>The <literal>accesscontrollist</literal> Tag</title> <title>The <literal>accesscontrollist</literal> Tag</title>
@ -80,13 +80,13 @@ represented by the values "1" or "2" on the given object.
&lt;/sec:accesscontrollist></programlisting></para> &lt;/sec:accesscontrollist></programlisting></para>
<para>The permissions are passed to the <interfacename>PermissionFactory</interfacename> <para>The permissions are passed to the <interfacename>PermissionFactory</interfacename>
defined in the application context, converting them to ACL defined in the application context, converting them to ACL
<interfacename>Permission</interfacename> instances, so they may be any format which <interfacename>Permission</interfacename> instances, so they may be any format which is
is supported by the factory - they don't have to be integers, they could be strings like supported by the factory - they don't have to be integers, they could be strings like
<literal>READ</literal> or <literal>WRITE</literal>. If no <literal>READ</literal> or <literal>WRITE</literal>. If no
<interfacename>PermissionFactory</interfacename> is found, an instance of <interfacename>PermissionFactory</interfacename> is found, an instance of
<classname>DefaultPermissionFactory</classname> will be used. The <classname>DefaultPermissionFactory</classname> will be used. The
<interfacename>AclService</interfacename>from the application context will be used <interfacename>AclService</interfacename>from the application context will be used to
to load the <interfacename>Acl</interfacename> instance for the supplied object. The load the <interfacename>Acl</interfacename> instance for the supplied object. The
<interfacename>Acl</interfacename> will be invoked with the required permissions to <interfacename>Acl</interfacename> will be invoked with the required permissions to
check if any of them are granted.</para> check if any of them are granted.</para>
</section> </section>

File diff suppressed because it is too large Load Diff

View File

@ -7,29 +7,32 @@
<section xml:id="filters"> <section xml:id="filters">
<title>The Security Filter Chain</title> <title>The Security Filter Chain</title>
<para>Spring Security's web infrastructure is based entirely on standard servlet filters. It <para>Spring Security's web infrastructure is based entirely on standard servlet filters. It
doesn't use servlets or any other servlet-based frameworks (such as Spring MVC) internally, so doesn't use servlets or any other servlet-based frameworks (such as Spring MVC)
it has no strong links to any particular web technology. It deals in internally, so it has no strong links to any particular web technology. It deals in
<classname>HttpServletRequest</classname>s and <classname>HttpServletResponse</classname>s <classname>HttpServletRequest</classname>s and
and doesn't care whether the requests come from a browser, a web service client, an <classname>HttpServletResponse</classname>s and doesn't care whether the requests come
<classname>HttpInvoker</classname> or an AJAX application. </para> from a browser, a web service client, an <classname>HttpInvoker</classname> or an AJAX
application. </para>
<para> Spring Security maintains a filter chain internally where each of the filters has a <para> Spring Security maintains a filter chain internally where each of the filters has a
particular responsibility and filters are added or removed from the configuration depending on particular responsibility and filters are added or removed from the configuration
which services are required. The ordering of the filters is important as there are depending on which services are required. The ordering of the filters is important as
dependencies between them. If you have been using <link xlink:href="#ns-config">namespace there are dependencies between them. If you have been using <link
configuration</link>, then the filters are automatically configured for you and you don't xlink:href="#ns-config">namespace configuration</link>, then the filters are
have to define any Spring beans explicitly but here may be times when you want full control automatically configured for you and you don't have to define any Spring beans
over the security filter chain, either because you are using features which aren't supported explicitly but here may be times when you want full control over the security filter
in the namespace, or you are using your own customized versions of classes.</para> chain, either because you are using features which aren't supported in the namespace, or
you are using your own customized versions of classes.</para>
<section xml:id="delegating-filter-proxy"> <section xml:id="delegating-filter-proxy">
<title><classname>DelegatingFilterProxy</classname></title> <title><classname>DelegatingFilterProxy</classname></title>
<para> When using servlet filters, you obviously need to declare them in your <para> When using servlet filters, you obviously need to declare them in your
<filename>web.xml</filename>, or they will be ignored by the servlet container. In Spring <filename>web.xml</filename>, or they will be ignored by the servlet container. In
Security, the filter classes are also Spring beans defined in the application context and Spring Security, the filter classes are also Spring beans defined in the application
thus able to take advantage of Spring's rich dependency-injection facilities and lifecycle context and thus able to take advantage of Spring's rich dependency-injection
interfaces. Spring's <classname>DelegatingFilterProxy</classname> provides the link between facilities and lifecycle interfaces. Spring's
<classname>DelegatingFilterProxy</classname> provides the link between
<filename>web.xml</filename> and the application context. </para> <filename>web.xml</filename> and the application context. </para>
<para>When using <classname>DelegatingFilterProxy</classname>, you will see something like <para>When using <classname>DelegatingFilterProxy</classname>, you will see something
this in the <filename>web.xml</filename> file: <programlisting><![CDATA[ like this in the <filename>web.xml</filename> file: <programlisting><![CDATA[
<filter> <filter>
<filter-name>myFilter</filter-name> <filter-name>myFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
@ -40,29 +43,31 @@
<url-pattern>/*</url-pattern> <url-pattern>/*</url-pattern>
</filter-mapping>]]> </filter-mapping>]]>
</programlisting> Notice that the filter is actually a </programlisting> Notice that the filter is actually a
<literal>DelegatingFilterProxy</literal>, and not the class that will actually implement <literal>DelegatingFilterProxy</literal>, and not the class that will actually
the logic of the filter. What <classname>DelegatingFilterProxy</classname> does is delegate implement the logic of the filter. What <classname>DelegatingFilterProxy</classname>
the <interfacename>Filter</interfacename>'s methods through to a bean which is obtained from does is delegate the <interfacename>Filter</interfacename>'s methods through to a
the Spring application context. This enables the bean to benefit from the Spring web bean which is obtained from the Spring application context. This enables the bean to
application context lifecycle support and configuration flexibility. The bean must implement benefit from the Spring web application context lifecycle support and configuration
<interfacename>javax.servlet.Filter</interfacename> and it must have the same name as that flexibility. The bean must implement
in the <literal>filter-name</literal> element. Read the Javadoc for <interfacename>javax.servlet.Filter</interfacename> and it must have the same name
as that in the <literal>filter-name</literal> element. Read the Javadoc for
<classname>DelegatingFilterProxy</classname> for more information</para> <classname>DelegatingFilterProxy</classname> for more information</para>
</section> </section>
<section xml:id="filter-chain-proxy"> <section xml:id="filter-chain-proxy">
<title><classname>FilterChainProxy</classname></title> <title><classname>FilterChainProxy</classname></title>
<para> It should now be clear that you can declare each Spring Security filter bean that you <para> It should now be clear that you can declare each Spring Security filter bean that
require in your application context file and add a corresponding you require in your application context file and add a corresponding
<classname>DelegatingFilterProxy</classname> entry to <filename>web.xml</filename> for <classname>DelegatingFilterProxy</classname> entry to <filename>web.xml</filename>
each filter, making sure that they are ordered correctly. This is a cumbersome approach and for each filter, making sure that they are ordered correctly. This is a cumbersome
clutters up the <filename>web.xml</filename> file quickly if we have a lot of filters. We approach and clutters up the <filename>web.xml</filename> file quickly if we have a
would prefer to just add a single entry to <filename>web.xml</filename> and deal entirely lot of filters. We would prefer to just add a single entry to
with the application context file for managing our web security beans. This is where Spring <filename>web.xml</filename> and deal entirely with the application context file for
Secuiryt's <classname>FilterChainProxy</classname> comes in. It is wired using a managing our web security beans. This is where Spring Secuiryt's
<literal>DelegatingFilterProxy</literal>, just like in the example above, but with the <classname>FilterChainProxy</classname> comes in. It is wired using a
<literal>filter-name</literal> set to the bean name <quote>filterChainProxy</quote>. The <literal>DelegatingFilterProxy</literal>, just like in the example above, but with
filter chain is then declared in the application context with the same bean name. Here's an the <literal>filter-name</literal> set to the bean name
example: <programlisting language="xml"><![CDATA[ <quote>filterChainProxy</quote>. The filter chain is then declared in the
application context with the same bean name. Here's an example: <programlisting language="xml"><![CDATA[
<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy"> <bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
<sec:filter-chain-map path-type="ant"> <sec:filter-chain-map path-type="ant">
<sec:filter-chain pattern="/webServices/**" filters=" <sec:filter-chain pattern="/webServices/**" filters="
@ -78,127 +83,134 @@
</sec:filter-chain-map> </sec:filter-chain-map>
</bean> </bean>
]]> ]]>
</programlisting> The namespace element <literal>filter-chain-map</literal> is </programlisting> The namespace element <literal>filter-chain-map</literal> is used to set
used to set up the security filter chain(s) which are required within the application<footnote> up the security filter chain(s) which are required within the application<footnote>
<para>Note that you'll need to include the security namespace in your application context <para>Note that you'll need to include the security namespace in your application
XML file in order to use this syntax.</para> context XML file in order to use this syntax.</para>
</footnote>. It maps a particular URL pattern to a chain of filters built up from the bean </footnote>. It maps a particular URL pattern to a chain of filters built up from
names specified in the <literal>filters</literal> element. Both regular expressions and Ant the bean names specified in the <literal>filters</literal> element. Both regular
Paths are supported, and the most specific URIs appear first. At runtime the expressions and Ant Paths are supported, and the most specific URIs appear first. At
<classname>FilterChainProxy</classname> will locate the first URI pattern that matches the runtime the <classname>FilterChainProxy</classname> will locate the first URI
current web request and the list of filter beans specified by the <literal>filters</literal> pattern that matches the current web request and the list of filter beans specified
attribute will be applied to that request. The filters will be invoked in the order they are by the <literal>filters</literal> attribute will be applied to that request. The
defined, so you have complete control over the filter chain which is applied to a particular filters will be invoked in the order they are defined, so you have complete control
URL.</para> over the filter chain which is applied to a particular URL.</para>
<para>You may have noticed we have declared two <para>You may have noticed we have declared two
<classname>SecurityContextPersistenceFilter</classname>s in the filter chain <classname>SecurityContextPersistenceFilter</classname>s in the filter chain
(<literal>ASC</literal> is short for <literal>allowSessionCreation</literal>, a property (<literal>ASC</literal> is short for <literal>allowSessionCreation</literal>, a
of <classname>SecurityContextPersistenceFilter</classname>). As web services will never property of <classname>SecurityContextPersistenceFilter</classname>). As web
present a <literal>jsessionid</literal> on future requests, creating services will never present a <literal>jsessionid</literal> on future requests,
<literal>HttpSession</literal>s for such user agents would be wasteful. If you had a creating <literal>HttpSession</literal>s for such user agents would be wasteful. If
high-volume application which required maximum scalability, we recommend you use the you had a high-volume application which required maximum scalability, we recommend
approach shown above. For smaller applications, using a single you use the approach shown above. For smaller applications, using a single
<classname>SecurityContextPersistenceFilter</classname> (with its default <classname>SecurityContextPersistenceFilter</classname> (with its default
<literal>allowSessionCreation</literal> as <literal>true</literal>) would likely be <literal>allowSessionCreation</literal> as <literal>true</literal>) would likely be
sufficient.</para> sufficient.</para>
<para>In relation to lifecycle issues, the <classname>FilterChainProxy</classname> will always <para>In relation to lifecycle issues, the <classname>FilterChainProxy</classname> will
delegate <methodname>init(FilterConfig)</methodname> and <methodname>destroy()</methodname> always delegate <methodname>init(FilterConfig)</methodname> and
methods through to the underlaying <interfacename>Filter</interfacename>s if such methods <methodname>destroy()</methodname> methods through to the underlaying
are called against <classname>FilterChainProxy</classname> itself. In this case, <interfacename>Filter</interfacename>s if such methods are called against
<classname>FilterChainProxy</classname> guarantees to only initialize and destroy each <classname>FilterChainProxy</classname> itself. In this case,
<literal>Filter</literal> bean once, no matter how many times it is declared in the filter <classname>FilterChainProxy</classname> guarantees to only initialize and destroy
chain(s). You control the overall choice as to whether these methods are called or not via each <literal>Filter</literal> bean once, no matter how many times it is declared in
the <literal>targetFilterLifecycle</literal> initialization parameter of the filter chain(s). You control the overall choice as to whether these methods are
<literal>DelegatingFilterProxy</literal>. By default this property is called or not via the <literal>targetFilterLifecycle</literal> initialization
<literal>false</literal> and servlet container lifecycle invocations are not delegated parameter of <literal>DelegatingFilterProxy</literal>. By default this property is
through <literal>DelegatingFilterProxy</literal>.</para> <literal>false</literal> and servlet container lifecycle invocations are not
delegated through <literal>DelegatingFilterProxy</literal>.</para>
<para> When we looked at how to set up web security using <link <para> When we looked at how to set up web security using <link
xlink:href="#namespace-auto-config">namespace configuration</link>, we used a xlink:href="#namespace-auto-config">namespace configuration</link>, we used a
<literal>DelegatingFilterProxy</literal> with the name <literal>DelegatingFilterProxy</literal> with the name
<quote>springSecurityFilterChain</quote>. You should now be able to see that this is the <quote>springSecurityFilterChain</quote>. You should now be able to see that this is
name of the <classname>FilterChainProxy</classname> which is created by the namespace. </para> the name of the <classname>FilterChainProxy</classname> which is created by the
namespace. </para>
<section> <section>
<title>Bypassing the Filter Chain</title> <title>Bypassing the Filter Chain</title>
<para> As with the namespace, you can use the attribute <literal>filters = "none"</literal> <para> As with the namespace, you can use the attribute <literal>filters =
as an alternative to supplying a filter bean list. This will omit the request pattern from "none"</literal> as an alternative to supplying a filter bean list. This will
the security filter chain entirely. Note that anything matching this path will then have omit the request pattern from the security filter chain entirely. Note that
no authentication or authorization services applied and will be freely accessible. If you anything matching this path will then have no authentication or authorization
want to make use of the contents of the <classname>SecurityContext</classname> contents services applied and will be freely accessible. If you want to make use of the
during a request, then it must have passed through the security filter chain. Otherwise contents of the <classname>SecurityContext</classname> contents during a
the <classname>SecurityContextHolder</classname> will not have been populated and the request, then it must have passed through the security filter chain. Otherwise
contents will be null.</para> the <classname>SecurityContextHolder</classname> will not have been populated
and the contents will be null.</para>
</section> </section>
</section> </section>
<section> <section>
<title>Filter Ordering</title> <title>Filter Ordering</title>
<para>The order that filters are defined in the chain is very important. Irrespective of which <para>The order that filters are defined in the chain is very important. Irrespective of
filters you are actually using, the order should be as follows: which filters you are actually using, the order should be as follows: <orderedlist>
<orderedlist>
<listitem> <listitem>
<para><classname>ChannelProcessingFilter</classname>, because it might need to redirect <para><classname>ChannelProcessingFilter</classname>, because it might need to
to a different protocol</para> redirect to a different protocol</para>
</listitem> </listitem>
<listitem> <listitem>
<para><classname>ConcurrentSessionFilter</classname>, because it doesn't use any <para><classname>ConcurrentSessionFilter</classname>, because it doesn't use any
<classname>SecurityContextHolder</classname> functionality but needs to update the <classname>SecurityContextHolder</classname> functionality but needs to
<interfacename>SessionRegistry</interfacename> to reflect ongoing requests from the update the <interfacename>SessionRegistry</interfacename> to reflect ongoing
principal</para> requests from the principal</para>
</listitem> </listitem>
<listitem> <listitem>
<para><classname>SecurityContextPersistenceFilter</classname>, so a <para><classname>SecurityContextPersistenceFilter</classname>, so a
<interfacename>SecurityContext</interfacename> can be set up in the <interfacename>SecurityContext</interfacename> can be set up in the
<classname>SecurityContextHolder</classname> at the beginning of a web request, and <classname>SecurityContextHolder</classname> at the beginning of a web
any changes to the <interfacename>SecurityContext</interfacename> can be copied to the request, and any changes to the
<literal>HttpSession</literal> when the web request ends (ready for use with the <interfacename>SecurityContext</interfacename> can be copied to the
next web request)</para> <literal>HttpSession</literal> when the web request ends (ready for use with
the next web request)</para>
</listitem> </listitem>
<listitem> <listitem>
<para>Authentication processing mechanisms - <para>Authentication processing mechanisms -
<classname>UsernamePasswordAuthenticationFilter</classname>, <classname>UsernamePasswordAuthenticationFilter</classname>,
<classname>CasProcessingFilter</classname>, <classname>CasProcessingFilter</classname>,
<classname>BasicProcessingFilter</classname> etc - so that the <classname>BasicProcessingFilter</classname> etc - so that the
<classname>SecurityContextHolder</classname> can be modified to contain a valid <classname>SecurityContextHolder</classname> can be modified to contain a
<interfacename>Authentication</interfacename> request token</para> valid <interfacename>Authentication</interfacename> request token</para>
</listitem> </listitem>
<listitem> <listitem>
<para>The <literal>SecurityContextHolderAwareRequestFilter</literal>, if you are using <para>The <literal>SecurityContextHolderAwareRequestFilter</literal>, if you are
it to install a Spring Security aware <literal>HttpServletRequestWrapper</literal> using it to install a Spring Security aware
into your servlet container</para> <literal>HttpServletRequestWrapper</literal> into your servlet
container</para>
</listitem> </listitem>
<listitem> <listitem>
<para><classname>RememberMeProcessingFilter</classname>, so that if no earlier <para><classname>RememberMeProcessingFilter</classname>, so that if no earlier
authentication processing mechanism updated the authentication processing mechanism updated the
<classname>SecurityContextHolder</classname>, and the request presents a cookie that <classname>SecurityContextHolder</classname>, and the request presents a
enables remember-me services to take place, a suitable remembered cookie that enables remember-me services to take place, a suitable
<interfacename>Authentication</interfacename> object will be put there</para> remembered <interfacename>Authentication</interfacename> object will be put
there</para>
</listitem> </listitem>
<listitem> <listitem>
<para><classname>AnonymousProcessingFilter</classname>, so that if no earlier <para><classname>AnonymousProcessingFilter</classname>, so that if no earlier
authentication processing mechanism updated the authentication processing mechanism updated the
<classname>SecurityContextHolder</classname>, an anonymous <classname>SecurityContextHolder</classname>, an anonymous
<interfacename>Authentication</interfacename> object will be put there</para> <interfacename>Authentication</interfacename> object will be put
there</para>
</listitem> </listitem>
<listitem> <listitem>
<para><classname>ExceptionTranslationFilter</classname>, to catch any Spring Security <para><classname>ExceptionTranslationFilter</classname>, to catch any Spring
exceptions so that either an HTTP error response can be returned or an appropriate Security exceptions so that either an HTTP error response can be returned or
<interfacename>AuthenticationEntryPoint</interfacename> can be launched</para> an appropriate <interfacename>AuthenticationEntryPoint</interfacename> can
be launched</para>
</listitem> </listitem>
<listitem> <listitem>
<para><classname>FilterSecurityInterceptor</classname>, to protect web URIs and raise <para><classname>FilterSecurityInterceptor</classname>, to protect web URIs and
exceptions when access is denied</para> raise exceptions when access is denied</para>
</listitem> </listitem>
</orderedlist></para> </orderedlist></para>
</section> </section>
<section> <section>
<title>Use with other Filter-Based Frameworks</title> <title>Use with other Filter-Based Frameworks</title>
<para>If you're using some other framework that is also filter-based, then you need to make <para>If you're using some other framework that is also filter-based, then you need to
sure that the Spring Security filters come first. This enables the make sure that the Spring Security filters come first. This enables the
<classname>SecurityContextHolder</classname> to be populated in time for use by the other <classname>SecurityContextHolder</classname> to be populated in time for use by the
filters. Examples are the use of SiteMesh to decorate your web pages or a web framework like other filters. Examples are the use of SiteMesh to decorate your web pages or a web
Wicket which uses a filter to handle its requests. </para> framework like Wicket which uses a filter to handle its requests. </para>
</section> </section>
</section> </section>
<!-- <!--
<section xml:id="taglib"> <section xml:id="taglib">
<info> <info>
<title>Tag Libraries</title> <title>Tag Libraries</title>

View File

@ -1,7 +1,12 @@
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="x509"> <chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="x509">
<info><title>X.509 Authentication</title></info> <info>
<title>X.509 Authentication</title>
</info>
<section xml:id="x509-overview"><info><title>Overview</title></info> <section xml:id="x509-overview">
<info>
<title>Overview</title>
</info>
<para>The most common use of X.509 certificate authentication is in verifying the identity <para>The most common use of X.509 certificate authentication is in verifying the identity
of a server when using SSL, most commonly when using HTTPS from a browser. The browser of a server when using SSL, most commonly when using HTTPS from a browser. The browser
@ -10,37 +15,46 @@
maintains.</para> maintains.</para>
<para>You can also use SSL with <quote>mutual authentication</quote>; the server will then <para>You can also use SSL with <quote>mutual authentication</quote>; the server will then
request a valid certificate from the client as part of the SSL handshake. The server request a valid certificate from the client as part of the SSL handshake. The server
will authenticate the client by checking that its certificate is signed by an will authenticate the client by checking that its certificate is signed by an acceptable
acceptable authority. If a valid certificate has been provided, it can be obtained authority. If a valid certificate has been provided, it can be obtained through the
through the servlet API in an application. Spring Security X.509 module extracts the servlet API in an application. Spring Security X.509 module extracts the certificate
certificate using a filter. It maps the certificate to an application user and loads that using a filter. It maps the certificate to an application user and loads that user's set
user's set of granted authorities for use with the standard Spring Security infrastructure.</para> of granted authorities for use with the standard Spring Security infrastructure.</para>
<para>You should be familiar with using certificates and setting up client authentication <para>You should be familiar with using certificates and setting up client authentication
for your servlet container before attempting to use it with Spring Security. Most of the for your servlet container before attempting to use it with Spring Security. Most of the
work is in creating and installing suitable certificates and keys. For example, if work is in creating and installing suitable certificates and keys. For example, if
you're using Tomcat then read the instructions here <uri xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html">http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html</uri>. It's important that you're using Tomcat then read the instructions here <uri
you get this working before trying it out with Spring Security</para> xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html"
>http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html</uri>. It's important that you
get this working before trying it out with Spring Security</para>
</section> </section>
<section><info><title>Adding X.509 Authentication to Your Web Application</title></info> <section>
<info>
<title>Adding X.509 Authentication to Your Web Application</title>
</info>
<para> Enabling X.509 client authentication is very straightforward. Just add the <literal>&lt;x509/&gt;</literal> element to your http security namespace configuration. <programlisting> <para> Enabling X.509 client authentication is very straightforward. Just add the
<literal>&lt;x509/&gt;</literal> element to your http security namespace configuration.
<programlisting>
&lt;http&gt; &lt;http&gt;
... ...
&lt;x509 subject-principal-regex="CN=(.*?)," user-service-ref="userService"/&gt; &lt;x509 subject-principal-regex="CN=(.*?)," user-service-ref="userService"/&gt;
... ...
&lt;/http&gt; &lt;/http&gt;
</programlisting> The element has two optional attributes: <itemizedlist> </programlisting>
The element has two optional attributes: <itemizedlist>
<listitem> <listitem>
<para><literal>subject-principal-regex</literal>. The regular expression used to <para><literal>subject-principal-regex</literal>. The regular expression used to
extract a username from the certificate's subject name. The default value is extract a username from the certificate's subject name. The default value is
shown above. This is the username which will be passed to the <interfacename>UserDetailsService</interfacename> to load the authorities for the shown above. This is the username which will be passed to the
user.</para> <interfacename>UserDetailsService</interfacename> to load the authorities for
the user.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><literal>user-service-ref</literal>. This is the bean Id of the <para><literal>user-service-ref</literal>. This is the bean Id of the
<interfacename>UserDetailsService</interfacename> to be used with X.509. <interfacename>UserDetailsService</interfacename> to be used with X.509. It
It isn't needed if there is only one defined in your application isn't needed if there is only one defined in your application context.</para>
context.</para>
</listitem> </listitem>
</itemizedlist> The <literal>subject-principal-regex</literal> should contain a single </itemizedlist> The <literal>subject-principal-regex</literal> should contain a single
group. For example the default expression "CN=(.*?)," matches the common name field. So group. For example the default expression "CN=(.*?)," matches the common name field. So
@ -54,19 +68,19 @@
authentication with other options such as a form-based login. </para> authentication with other options such as a form-based login. </para>
</section> </section>
<section xml:id="x509-ssl-config"> <section xml:id="x509-ssl-config">
<info><title>Setting up SSL in Tomcat</title></info> <info>
<title>Setting up SSL in Tomcat</title>
</info>
<para>There are some pre-generated certificates in the <para>There are some pre-generated certificates in the
<filename>samples/certificate</filename> directory in the Spring Security project. <filename>samples/certificate</filename> directory in the Spring Security project. You
You can use these to enable SSL for testing if you don't want to generate your own. The file can use these to enable SSL for testing if you don't want to generate your own. The file
<filename>server.jks</filename> contains the server certificate, private key and the <filename>server.jks</filename> contains the server certificate, private key and the
issuing certificate authority certificate. There are also some client certificate files issuing certificate authority certificate. There are also some client certificate files
for the users from the sample applications. You can install these in your browser to enable for the users from the sample applications. You can install these in your browser to
SSL client authentication. enable SSL client authentication. </para>
</para> <para> To run tomcat with SSL support, drop the <filename>server.jks</filename> file into
<para> the tomcat <filename>conf</filename> directory and add the following connector to the
To run tomcat with SSL support, drop the <filename>server.jks</filename> file into the
tomcat <filename>conf</filename> directory and add the following connector to the
<filename>server.xml</filename> file <filename>server.xml</filename> file
<programlisting> <programlisting>
&lt;Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" scheme="https" secure="true" &lt;Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" scheme="https" secure="true"
@ -77,10 +91,10 @@
truststoreType="JKS" truststorePass="password" truststoreType="JKS" truststorePass="password"
/&gt; /&gt;
</programlisting> </programlisting>
<parameter>clientAuth</parameter> can also be set to <parameter>want</parameter> if you still <parameter>clientAuth</parameter> can also be set to <parameter>want</parameter> if you
want SSL connections to succeed even if the client doesn't provide a certificate. still want SSL connections to succeed even if the client doesn't provide a certificate.
Clients which don't present a certificate won't be able to access any objects secured by Clients which don't present a certificate won't be able to access any objects secured by
Spring Security unless you use a non-X.509 authentication mechanism, such as form authentication. Spring Security unless you use a non-X.509 authentication mechanism, such as form
</para> authentication. </para>
</section> </section>
</chapter> </chapter>