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

View File

@ -4,16 +4,17 @@
<info>
<title>Security Database Schema</title>
</info>
<para> There are various database schema used by the framework and this appendix provides a single
reference point to them all. You only need to provide the tables for the areas of functonality
you require. </para>
<para> There are various database schema used by the framework and this appendix provides a
single reference point to them all. You only need to provide the tables for the areas of
functonality you require. </para>
<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>
<section>
<title>User Schema</title>
<para> The standard JDBC implementation of the <interfacename>UserDetailsService</interfacename>
(<classname>JdbcDaoImpl</classname>) requires tables to load the password, account status
(enabled or disabled) and a list of authorities (roles) for the user.
<para> The standard JDBC implementation of the
<interfacename>UserDetailsService</interfacename> (<classname>JdbcDaoImpl</classname>)
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">
create table users(
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"
>ACL</link> implementation. <orderedlist>
<listitem>
<para><literal>acl_sid</literal> stores the security identities recognised by the ACL
system. These can be unique principals or authorities which may apply to multiple
principals.</para>
<para><literal>acl_sid</literal> stores the security identities recognised by the
ACL system. These can be unique principals or authorities which may apply to
multiple principals.</para>
</listitem>
<listitem>
<para><literal>acl_class</literal> defines the domain object types to which ACLs apply.
The <literal>class</literal> column stores the Java class name of the object. </para>
<para><literal>acl_class</literal> defines the domain object types to which ACLs
apply. The <literal>class</literal> column stores the Java class name of the
object. </para>
</listitem>
<listitem>
<para><literal>acl_object_identity</literal> stores the object identity definitions of
specific domai objects.</para>
<para><literal>acl_object_identity</literal> stores the object identity definitions
of specific domai objects.</para>
</listitem>
<listitem>
<para><literal>acl_entry</literal> stores the ACL permissions which apply to a specific
object identity and security identity.</para>
<para><literal>acl_entry</literal> stores the ACL permissions which apply to a
specific object identity and security identity.</para>
</listitem>
</orderedlist></para>
<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
it has created a new row in the <literal>acl_sid</literal> or <literal>acl_class</literal>
tables. It has two properties which define the SQL needed to retrieve these values
<literal>classIdentityQuery</literal> and <literal>sidIdentityQuery</literal>. Both of these
default to <literal>call identity()</literal></para>
identities. The <literal>JdbcMutableAclService</literal> has to be able to retrieve
these when it has created a new row in the <literal>acl_sid</literal> or
<literal>acl_class</literal> tables. It has two properties which define the SQL needed
to retrieve these values <literal>classIdentityQuery</literal> and
<literal>sidIdentityQuery</literal>. Both of these default to <literal>call
identity()</literal></para>
<section>
<title>Hypersonic SQL</title>
<para>The default schema works with the embedded HSQLDB database that is used in unit tests
within the
<para>The default schema works with the embedded HSQLDB database that is used in unit
tests within the
framework.<programlisting xml:id="dbschema-acl-hsql">
create table acl_sid (
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)
references acl_object_identity(id),
constraint foreign_fk_5 foreign key(sid) references acl_sid(id));
</programlisting>
</para>
</programlisting> </para>
<para>You will have to set the <literal>classIdentityQuery</literal> and
<literal>sidIdentityQuery</literal> properties of
<classname>JdbcMutableAclService</classname> to the following values, respectively: <itemizedlist>
<classname>JdbcMutableAclService</classname> to the following values,
respectively: <itemizedlist>
<listitem>
<para><literal>select currval(pg_get_serial_sequence('acl_class',
'id'))</literal></para>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -42,7 +42,7 @@
</info>
<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"
>http://forum.springsource.org</uri> to discuss Spring Security with other users of
the framework. Remember to use JIRA for bug reports, as explained above.</para>
>http://forum.springsource.org</uri> to discuss Spring Security with other users of the
framework. Remember to use JIRA for bug reports, as explained above.</para>
</section>
</chapter>

View File

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

View File

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

View File

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

View File

@ -9,9 +9,9 @@
<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
comprise both who (<interfacename>Authentication</interfacename>), where
(<classname>MethodInvocation</classname>) and what (<literal>SomeDomainObject</literal>). In
other words, authorization decisions also need to consider the actual domain object
instance subject of a method invocation.</para>
(<classname>MethodInvocation</classname>) and what
(<literal>SomeDomainObject</literal>). In other words, authorization decisions also need
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
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
@ -29,42 +29,42 @@
object.</para>
</listitem>
<listitem>
<para>Write an <interfacename>AccessDecisionVoter</interfacename> to enforce the security
from the <literal>GrantedAuthority[]</literal>s stored in the
<para>Write an <interfacename>AccessDecisionVoter</interfacename> to enforce the
security from the <literal>GrantedAuthority[]</literal>s stored in the
<interfacename>Authentication</interfacename> object. This would mean your
<interfacename>AuthenticationManager</interfacename> would need to populate the
<interfacename>Authentication</interfacename> with custom
<interfacename>GrantedAuthority</interfacename>[]s representing each of the
<literal>Customer</literal> domain object instances the principal has
access to.</para>
<literal>Customer</literal> domain object instances the principal has access
to.</para>
</listitem>
<listitem>
<para>Write an <interfacename>AccessDecisionVoter</interfacename> to enforce the security
and open the target <literal>Customer</literal> domain object directly. This
would mean your voter needs access to a DAO that allows it to retrieve the
<para>Write an <interfacename>AccessDecisionVoter</interfacename> to enforce the
security and open the target <literal>Customer</literal> domain object directly.
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's collection of approved users and
make the appropriate decision.</para>
<literal>Customer</literal> object's collection of approved users and make the
appropriate decision.</para>
</listitem>
</orderedlist></para>
<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
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>GrantedAuthority[]</literal>s from the <interfacename>Authentication</interfacename>
object is also fine, but will not scale to large numbers of
<literal>Customer</literal>s. If a user might be able to access 5,000
<literal>GrantedAuthority[]</literal>s from the
<interfacename>Authentication</interfacename> object is also fine, but will not scale to
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
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,
opening the <literal>Customer</literal> directly from external code, is probably the
best of the three. It achieves separation of concerns, and doesn't misuse memory or CPU
cycles, but it is still inefficient in that both the
<interfacename>AccessDecisionVoter</interfacename> and the eventual business method itself will
perform a call to the DAO responsible for retrieving the <literal>Customer</literal>
object. Two accesses per method invocation is clearly undesirable. In addition, with
every approach listed you'll need to write your own access control list (ACL)
persistence and business logic from scratch.</para>
the <interfacename>Authentication</interfacename> object would be undesirable. The final
method, opening the <literal>Customer</literal> directly from external code, is probably
the best of the three. It achieves separation of concerns, and doesn't misuse memory or
CPU cycles, but it is still inefficient in that both the
<interfacename>AccessDecisionVoter</interfacename> and the eventual business method
itself will perform a call to the DAO responsible for retrieving the
<literal>Customer</literal> object. Two accesses per method invocation is clearly
undesirable. In addition, with every approach listed you'll need to write your own
access control list (ACL) persistence and business logic from scratch.</para>
<para>Fortunately, there is another alternative, which we'll talk about below.</para>
</section>
<section xml:id="domain-acls-key-concepts">
@ -83,12 +83,12 @@
(and modifying those ACLs)</para>
</listitem>
<listitem>
<para>A way of ensuring a given principal is permitted to work with your
objects, before methods are called</para>
<para>A way of ensuring a given principal is permitted to work with your objects,
before methods are called</para>
</listitem>
<listitem>
<para>A way of ensuring a given principal is permitted to work with your objects
(or something they return), after methods are called</para>
<para>A way of ensuring a given principal is permitted to work with your objects (or
something they return), after methods are called</para>
</listitem>
</itemizedlist></para>
<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
order of size in a typical Spring Security ACL deployment, with the table with the most
rows listed last:</para>
<para>
<itemizedlist>
<para> <itemizedlist>
<listitem>
<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,
a textual representation of the SID, and a flag to indicate whether the
textual representation refers to a principal name or a
system ("SID" stands for "security identity"). The only columns are the ID, a
textual representation of the SID, and a flag to indicate whether the textual
representation refers to a principal name or a
<interfacename>GrantedAuthority</interfacename>. Thus, there is a single row for
each unique principal or <interfacename>GrantedAuthority</interfacename>. When used in
the context of receiving a permission, a SID is generally called a
each unique principal or <interfacename>GrantedAuthority</interfacename>. When
used in the context of receiving a permission, a SID is generally called a
"recipient".</para>
</listitem>
<listitem>
<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
a single row for each unique Class we wish to store ACL permissions
for.</para>
system. The only columns are the ID and the Java class name. Thus, there is a
single row for each unique Class we wish to store ACL permissions for.</para>
</listitem>
<listitem>
<para>ACL_OBJECT_IDENTITY stores information for each unique domain object
instance in the system. Columns include the ID, a foreign key to the
ACL_CLASS table, a unique identifier so we know which ACL_CLASS instance
we're providing information for, the parent, a foreign key to the ACL_SID
table to represent the owner of the domain object instance, and whether we
allow ACL entries to inherit from any parent ACL. We have a single row for
every domain object instance we're storing ACL permissions for.</para>
<para>ACL_OBJECT_IDENTITY stores information for each unique domain object instance
in the system. Columns include the ID, a foreign key to the ACL_CLASS table, a
unique identifier so we know which ACL_CLASS instance we're providing
information for, the parent, a foreign key to the ACL_SID table to represent the
owner of the domain object instance, and whether we allow ACL entries to inherit
from any parent ACL. We have a single row for every domain object instance we're
storing ACL permissions for.</para>
</listitem>
<listitem>
<para>Finally, ACL_ENTRY stores the individual permissions assigned to each
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,
and the integer bit mask that represents the actual permission being granted
or denied. We have a single row for every recipient that receives a
permission to work with a domain object.</para>
recipient (ie a foreign key to ACL_SID), whether we'll be auditing or not, and
the integer bit mask that represents the actual permission being granted or
denied. We have a single row for every recipient that receives a permission to
work with a domain object.</para>
</listitem>
</itemizedlist>
</para>
</itemizedlist> </para>
<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,
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
<literal>Acl</literal> object, which internally holds 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,
but instead to an <literal>ObjectIdentity</literal>. The <literal>Acl</literal>
is stored in the ACL_OBJECT_IDENTITY table.</para>
<literal>Acl</literal>. An Acl does not refer directly to the domain object, but
instead to an <literal>ObjectIdentity</literal>. The <literal>Acl</literal> is
stored in the ACL_OBJECT_IDENTITY table.</para>
</listitem>
<listitem>
<para><literal>AccessControlEntry</literal>: An <literal>Acl</literal> holds
@ -183,11 +180,11 @@
</listitem>
<listitem>
<para><literal>Sid</literal>: The ACL module needs to refer to principals and
<literal>GrantedAuthority[]</literal>s. A level of indirection is provided
by the <literal>Sid</literal> interface, which is an abbreviation of "security
<literal>GrantedAuthority[]</literal>s. A level of indirection is provided by
the <literal>Sid</literal> interface, which is an abbreviation of "security
identity". Common classes include <literal>PrincipalSid</literal> (to represent
the principal inside an <interfacename>Authentication</interfacename> object) and
<literal>GrantedAuthoritySid</literal>. The security identity information is
the principal inside an <interfacename>Authentication</interfacename> object)
and <literal>GrantedAuthoritySid</literal>. The security identity information is
stored in the ACL_SID table.</para>
</listitem>
<listitem>
@ -227,15 +224,14 @@
ACL information somewhere. This necessitates the instantiation of a
<literal>DataSource</literal> using Spring. The <literal>DataSource</literal> is then
injected into a <literal>JdbcMutableAclService</literal> and
<literal>BasicLookupStrategy</literal> instance. The latter provides
high-performance ACL retrieval capabilities, and the former provides mutator
capabilities. Refer to one of the samples that ship with Spring Security for an example
configuration. You'll also need to populate the database with the four ACL-specific
tables listed in the last section (refer to the ACL samples for the appropriate SQL
statements).</para>
<literal>BasicLookupStrategy</literal> instance. The latter provides high-performance
ACL retrieval capabilities, and the former provides mutator capabilities. Refer to one
of the samples that ship with Spring Security for an example configuration. You'll also
need to populate the database with the four ACL-specific tables listed in the last
section (refer to the ACL samples for the appropriate SQL statements).</para>
<para>Once you've created the required schema and instantiated
<literal>JdbcMutableAclService</literal>, you'll next need to ensure your domain
model supports interoperability with the Spring Security ACL package. Hopefully
<literal>JdbcMutableAclService</literal>, you'll next need to ensure your domain model
supports interoperability with the Spring Security ACL package. Hopefully
<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
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
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
(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,
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
@ -282,15 +279,15 @@ aclService.updateAcl(acl);
<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
logic. You have a number of choices here. You could write your own
<interfacename>AccessDecisionVoter</interfacename> or <literal>AfterInvocationProvider</literal>
that respectively fires before or after a method invocation. Such classes would use
<literal>AclService</literal> to retrieve the relevant ACL and then call
<literal>Acl.isGranted(Permission[] permission, Sid[] sids, boolean
administrativeMode)</literal> to decide whether permission is granted or denied.
<interfacename>AccessDecisionVoter</interfacename> or
<literal>AfterInvocationProvider</literal> that respectively fires before or after a
method invocation. Such classes would use <literal>AclService</literal> to retrieve the
relevant ACL and then call <literal>Acl.isGranted(Permission[] permission, Sid[] sids,
boolean administrativeMode)</literal> to decide whether permission is granted or denied.
Alternately, you could use our <literal>AclEntryVoter</literal>,
<literal>AclEntryAfterInvocationProvider</literal> or
<literal>AclEntryAfterInvocationCollectionFilteringProvider</literal> classes. All
of these classes provide a declarative-based approach to evaluating ACL information at
<literal>AclEntryAfterInvocationCollectionFilteringProvider</literal> classes. All of
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
applications to learn how to use these classes.</para>
</section>

View File

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

View File

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

View File

@ -25,8 +25,8 @@
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
other system which can perform an action in your application).
<quote>Authorization</quote> refers to the process of deciding whether a principal
is allowed to perform an action within your application. To arrive at the point where an
<quote>Authorization</quote> refers to the process of deciding whether a principal is
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
established by the authentication process. These concepts are common, and not at all
specific to Spring Security. </para>
@ -134,8 +134,8 @@
</listitem>
</itemizedlist>
<para>(* Denotes provided by a third party; check our <link
xlink:href="http://acegisecurity.org/powering.html">integration page</link> for
links to the latest details)</para>
xlink:href="http://acegisecurity.org/powering.html">integration page</link> for links to
the latest details)</para>
<para>Many independent software vendors (ISVs) adopt Spring Security because of this
significant choice of flexible authentication models. Doing so allows them to quickly
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
contained on that page for your convenience:</para>
<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 API. MINOR versions retain source and binary compatibility with older minor
versions, and changes in the PATCH level are perfectly compatible, forwards and
The basic intent is that MAJOR versions are incompatible, large-scale upgrades of the
API. MINOR versions retain source and binary compatibility with older minor versions,
and changes in the PATCH level are perfectly compatible, forwards and
backwards.</quote></para>
</section>
<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
distribution from the main Spring <link
xlink:href="http://www.springsource.com/download/community?project=Spring%20Security"
>download page</link>, download individual jars (and sample WAR files) from the
Maven Central repository (or a SpringSource Maven repository for snapshot and milestone
>download page</link>, download individual jars (and sample WAR files) from the Maven
Central repository (or a SpringSource Maven repository for snapshot and milestone
releases) or, alternatively, you can build the project from source yourself. See the
project web site for more details. </para>
<section xml:id="modules">
@ -233,8 +233,23 @@
<para>Contains core authentication and access-contol classes and interfaces,
remoting support and basic provisioning APIs. Required by any application which
uses Spring Security. Supports standalone applications, remote clients, method
(service layer) security and JDBC user provisioning. Contains the top-level
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>
(service layer) security and JDBC user provisioning. Contains the top-level 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>
</section>
<section xml:id="spring-security-web">
<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">
<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">
<info><title>Overview</title></info>
<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>
<info>
<title>Overview</title>
</info>
<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
learn more about JAAS login configuration files, consult the JAAS
reference documentation available from Sun Microsystems. We expect you
to have a basic understanding of JAAS and its login configuration file
syntax in order to understand this section.</para>
<para>Central to JAAS operation are login configuration files. To learn more about JAAS
login configuration files, consult the JAAS reference documentation available from Sun
Microsystems. We expect you to have a basic understanding of JAAS and its login
configuration file syntax in order to understand this section.</para>
</section>
<section xml:id="jaas-config">
<info><title>Configuration</title></info>
<para>The <literal>JaasAuthenticationProvider</literal> attempts to
authenticate a users principal and credentials through JAAS.</para>
<info>
<title>Configuration</title>
</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,
<literal>/WEB-INF/login.conf</literal>, with the following
contents:
<programlisting>
<literal>/WEB-INF/login.conf</literal>, with the following contents:
<programlisting>
JAASTest {
sample.SampleLoginModule required;
};</programlisting></para>
<para>Like all Spring Security beans, the
<classname>JaasAuthenticationProvider</classname> is configured via the
application context. The following definitions would correspond to the
above JAAS login configuration file:
<programlisting><![CDATA[
<para>Like all Spring Security beans, the <classname>JaasAuthenticationProvider</classname>
is configured via the application context. The following definitions would correspond to
the above JAAS login configuration file: <programlisting><![CDATA[
<bean id="jaasAuthenticationProvider"
class="org.springframework.security.authentication.jaas.JaasAuthenticationProvider">
<property name="loginConfig" value="/WEB-INF/login.conf"/>
@ -55,82 +57,76 @@ JAASTest {
<interfacename>AuthorityGranter</interfacename>s are discussed below.</para>
<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
of some sort. These callbacks are usually used to obtain the
username and password from the user.</para>
<para>Most JAAS <literal>LoginModule</literal>s require a callback of some sort. These
callbacks are usually used to obtain the username and password from the user.</para>
<para>In a Spring Security deployment, Spring Security is
responsible for this user interaction (via the authentication
mechanism). Thus, by the time the authentication request is
delegated through to JAAS, Spring Security's authentication
mechanism will already have fully-populated an
<interfacename>Authentication</interfacename> object containing all the
information required by the JAAS
<para>In a Spring Security deployment, Spring Security is responsible for this user
interaction (via the authentication mechanism). Thus, by the time the authentication
request is delegated through to JAAS, Spring Security's authentication mechanism
will already have fully-populated an <interfacename>Authentication</interfacename>
object containing all the information required by the JAAS
<literal>LoginModule</literal>.</para>
<para>Therefore, the JAAS package for Spring Security provides two
default callback handlers,
<literal>JaasNameCallbackHandler</literal> and
<literal>JaasPasswordCallbackHandler</literal>. Each of these
callback handlers implement
<literal>JaasAuthenticationCallbackHandler</literal>. In most cases
these callback handlers can simply be used without understanding the
internal mechanics.</para>
<para>Therefore, the JAAS package for Spring Security provides two default callback
handlers, <literal>JaasNameCallbackHandler</literal> and
<literal>JaasPasswordCallbackHandler</literal>. Each of these callback handlers
implement <literal>JaasAuthenticationCallbackHandler</literal>. In most cases these
callback handlers can simply be used without understanding the internal
mechanics.</para>
<para>For those needing full control over the callback behavior,
internally <literal>JaasAuthenticationProvider</literal> wraps these
<para>For those needing full control over the callback behavior, internally
<literal>JaasAuthenticationProvider</literal> wraps these
<literal>JaasAuthenticationCallbackHandler</literal>s with an
<literal>InternalCallbackHandler</literal>. The
<literal>InternalCallbackHandler</literal> is the class that
actually implements JAAS normal <literal>CallbackHandler</literal>
interface. Any time that the JAAS <literal>LoginModule</literal> is
used, it is passed a list of application context configured
<literal>InternalCallbackHandler</literal>s. If the
<literal>InternalCallbackHandler</literal> is the class that actually implements
JAAS normal <literal>CallbackHandler</literal> interface. Any time that the JAAS
<literal>LoginModule</literal> is used, it is passed a list of application context
configured <literal>InternalCallbackHandler</literal>s. If the
<literal>LoginModule</literal> requests a callback against the
<literal>InternalCallbackHandler</literal>s, the callback is in-turn
passed to the <literal>JaasAuthenticationCallbackHandler</literal>s
being wrapped.</para>
<literal>InternalCallbackHandler</literal>s, the callback is in-turn passed to the
<literal>JaasAuthenticationCallbackHandler</literal>s being wrapped.</para>
</section>
<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
principals in JAAS. Spring Security, on the other hand, works with
<para>JAAS works with principals. Even "roles" are represented as principals in JAAS.
Spring Security, on the other hand, works with
<interfacename>Authentication</interfacename> objects. Each
<interfacename>Authentication</interfacename> object contains a single
principal, and multiple <interfacename>GrantedAuthority</interfacename>[]s. To
facilitate mapping between these different concepts, Spring
Security's JAAS package includes an
<interfacename>Authentication</interfacename> object contains a single principal,
and multiple <interfacename>GrantedAuthority</interfacename>[]s. To facilitate
mapping between these different concepts, Spring Security's JAAS package includes an
<literal>AuthorityGranter</literal> interface.</para>
<para>An <literal>AuthorityGranter</literal> is responsible for
inspecting a JAAS principal and returning a set of
<literal>String</literal>s, representing the authorities assigned to the principal.
For each returned authority string, the
<para>An <literal>AuthorityGranter</literal> is responsible for inspecting a JAAS
principal and returning a set of <literal>String</literal>s, representing the
authorities assigned to the principal. For each returned authority string, the
<classname>JaasAuthenticationProvider</classname> creates a
<classname>JaasGrantedAuthority</classname> (which implements Spring
Securitys <interfacename>GrantedAuthority</interfacename> interface) containing
the authority string and the JAAS principal that the
<classname>JaasGrantedAuthority</classname> (which implements Spring Securitys
<interfacename>GrantedAuthority</interfacename> interface) containing the authority
string and the JAAS principal that the
<interfacename>AuthorityGranter</interfacename> was passed. The
<classname>JaasAuthenticationProvider</classname> obtains the JAAS
principals by firstly successfully authenticating the users
credentials using the JAAS <literal>LoginModule</literal>, and then
accessing the <literal>LoginContext</literal> it returns. A call to
<literal>LoginContext.getSubject().getPrincipals()</literal> is
made, with each resulting principal passed to each
<interfacename>AuthorityGranter</interfacename> defined against the
<classname>JaasAuthenticationProvider</classname> obtains the JAAS principals by
firstly successfully authenticating the users credentials using the JAAS
<literal>LoginModule</literal>, and then accessing the
<literal>LoginContext</literal> it returns. A call to
<literal>LoginContext.getSubject().getPrincipals()</literal> is made, with each
resulting principal passed to each <interfacename>AuthorityGranter</interfacename>
defined against the
<literal>JaasAuthenticationProvider.setAuthorityGranters(List)</literal>
property.</para>
<para>Spring Security does not include any production
<interfacename>AuthorityGranter</interfacename>s given that every JAAS principal
has an implementation-specific meaning. However, there is a
<literal>TestAuthorityGranter</literal> in the unit tests that
demonstrates a simple <literal>AuthorityGranter</literal>
implementation.</para>
<interfacename>AuthorityGranter</interfacename>s given that every JAAS principal has
an implementation-specific meaning. However, there is a
<literal>TestAuthorityGranter</literal> in the unit tests that demonstrates a simple
<literal>AuthorityGranter</literal> implementation.</para>
</section>
</section>
</chapter>

View File

@ -17,12 +17,11 @@
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
xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="http://www.zytrax.com/books/ldap/"
>http://www.zytrax.com/books/ldap/</uri>. Some familiarity with the JNDI APIs used
to access LDAP from Java may also be useful. We don't use any third-party LDAP libraries
(Mozilla, JLDAP etc.) in the LDAP provider, but extensive use is made of Spring LDAP, so
some familiarity with that project may be useful if you plan on adding your own
customizations.</para>
xlink:href="http://www.zytrax.com/books/ldap/">http://www.zytrax.com/books/ldap/</uri>.
Some familiarity with the JNDI APIs used to access LDAP from Java may also be useful. We
don't use any third-party LDAP libraries (Mozilla, JLDAP etc.) in the LDAP provider, but
extensive use is made of Spring LDAP, so some familiarity with that project may be
useful if you plan on adding your own customizations.</para>
</section>
<section>
<info>
@ -31,9 +30,9 @@
<para> LDAP authentication in Spring Security can be roughly divided into the following
stages. <orderedlist inheritnum="ignore" continuation="restarts">
<listitem>
<para>Obtaining the unique LDAP <quote>Distinguished Name</quote>, or DN, from
the login name. This will often mean performing a search in the directory,
unless the exact mapping of usernames to DNs is known in advance.</para>
<para>Obtaining the unique LDAP <quote>Distinguished Name</quote>, or DN, from the
login name. This will often mean performing a search in the directory, unless
the exact mapping of usernames to DNs is known in advance.</para>
</listitem>
<listitem>
<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"/>
]]>
</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,
the namespace parser will create an embedded Apache Directory server and scan the
<quote>dc=springframework,dc=org</quote>, which is the default. Used this way, 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
customize this behaviour using the <literal>ldif</literal> attribute, which defines
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
following attributes. <itemizedlist>
<listitem>
<para>
<literal>group-search-base</literal>. Defines the part of the directory
<para> <literal>group-search-base</literal>. Defines the part of the directory
tree under which group searches should be performed.</para>
</listitem>
<listitem>
<para>
<literal>group-role-attribute</literal>. The attribute which contains
the name of the authority defined by the group entry. Defaults to
<literal>cn</literal>
</para>
<para> <literal>group-role-attribute</literal>. The attribute which contains the
name of the authority defined by the group entry. Defaults to
<literal>cn</literal> </para>
</listitem>
<listitem>
<para>
<literal>group-search-filter</literal>. The filter which is used to
<para> <literal>group-search-filter</literal>. The filter which is used to
search for group membership. The default is
<literal>uniqueMember={0}</literal>, corresponding to the
<literal>groupOfUniqueMembers</literal> LDAP class. In this case,
the substituted parameter is the full distinguished name of the user.
The parameter <literal>{1}</literal> can be used if you want to filter
on the login name.</para>
<literal>groupOfUniqueMembers</literal> LDAP class. In this case, the
substituted parameter is the full distinguished name of the user. The
parameter <literal>{1}</literal> can be used if you want to filter on the
login name.</para>
</listitem>
</itemizedlist> So if we used the following configuration <programlisting><![CDATA[
<ldap-authentication-provider user-dn-pattern="uid={0},ou=people"
group-search-base="ou=groups" />
]]></programlisting> and authenticated successfully as user <quote>ben</quote>, the subsequent
loading of authorities would perform a search under the directory entry
<literal>ou=groups,dc=springframework,dc=org</literal>, looking for entries
which contain the attribute <literal>uniqueMember</literal> with value
<literal>ou=groups,dc=springframework,dc=org</literal>, looking for entries which
contain the attribute <literal>uniqueMember</literal> with value
<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
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>
<para>There are currently two authentication strategies supplied with Spring Security: <itemizedlist>
<listitem>
<para>Authentication directly to the LDAP server ("bind"
authentication).</para>
<para>Authentication directly to the LDAP server ("bind" authentication).</para>
</listitem>
<listitem>
<para>Password comparison, where the password supplied by the user is
compared with the one stored in the repository. This can either be done
by retrieving the value of the password attribute and checking it
locally or by performing an LDAP "compare" operation, where the supplied
password is passed to the server for comparison and the real password
value is never retrieved.</para>
<para>Password comparison, where the password supplied by the user is compared
with the one stored in the repository. This can either be done by retrieving
the value of the password attribute and checking it locally or by performing
an LDAP "compare" operation, where the supplied password is passed to the
server for comparison and the real password value is never retrieved.</para>
</listitem>
</itemizedlist></para>
<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
application. This can be done either by simple pattern-matching (by setting the
<property>setUserDnPatterns</property> array property) or by setting the
<property>userSearch</property> property. For the DN pattern-matching
approach, a standard Java pattern format is used, and the login name will be
substituted for the parameter <parameter>{0}</parameter>. The pattern should be
relative to the DN that the configured
<interfacename>SpringSecurityContextSource</interfacename> will bind to (see
the section on <link linkend="ldap-context-source">connecting to the LDAP
server</link> for more information on this). For example, if you are using
an LDAP server with the URL
<property>userSearch</property> property. For the DN pattern-matching approach,
a standard Java pattern format is used, and the login name will be substituted
for the parameter <parameter>{0}</parameter>. The pattern should be relative to
the DN that the configured
<interfacename>SpringSecurityContextSource</interfacename> will bind to (see the
section on <link linkend="ldap-context-source">connecting to the LDAP
server</link> for more information on this). For example, if you are using an
LDAP server with the URL
<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
"gorilla" will map to a DN
<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
information on using a search, see the section on <link
linkend="ldap-searchobjects">search objects</link> below. A combination of
the two approaches can also be used - the patterns will be checked first and if
no matching DN is found, the search will be used.</para>
linkend="ldap-searchobjects">search objects</link> below. A combination of the
two approaches can also be used - the patterns will be checked first and if no
matching DN is found, the search will be used.</para>
</section>
<section xml:id="ldap-ldap-authenticators-bind">
<info>
<title>BindAuthenticator</title>
</info>
<para>The class <classname>BindAuthenticator</classname> in the package
<filename>org.springframework.security.ldap.authentication</filename>
implements the bind authentication strategy. It simply attempts to bind as the
user.</para>
<filename>org.springframework.security.ldap.authentication</filename> implements
the bind authentication strategy. It simply attempts to bind as the user.</para>
</section>
<section xml:id="ldap-ldap-authenticators-password">
<info>
@ -254,16 +246,15 @@
<info>
<title>LDAP Search Objects</title>
</info>
<para>Often a more complicated strategy than simple DN-matching is required to
locate a user entry in the directory. This can be encapsulated in an
<interfacename>LdapUserSearch</interfacename> instance which can be supplied to
the authenticator implementations, for example, to allow them to locate a user. The
<para>Often a more complicated strategy than simple DN-matching is required to locate a
user entry in the directory. This can be encapsulated in an
<interfacename>LdapUserSearch</interfacename> instance which can be supplied to the
authenticator implementations, for example, to allow them to locate a user. The
supplied implementation is <classname>FilterBasedLdapUserSearch</classname>.</para>
<section xml:id="ldap-searchobjects-filter">
<info>
<title xml:id="ldap-searchobjects-filter-based">
<classname>FilterBasedLdapUserSearch</classname>
</title>
<classname>FilterBasedLdapUserSearch</classname> </title>
</info>
<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
@ -281,11 +272,11 @@
<classname>LdapAuthenticationProvider</classname> will attempt to load a set of
authorities for the user by calling the configured
<interfacename>LdapAuthoritiesPopulator</interfacename> bean. The
<classname>DefaultLdapAuthoritiesPopulator</classname> is an implementation
which will load the authorities by searching the directory for groups of which the
user is a member (typically these will be <literal>groupOfNames</literal> or
<literal>groupOfUniqueNames</literal> entries in the directory). Consult the
Javadoc for this class for more details on how it works. </para>
<classname>DefaultLdapAuthoritiesPopulator</classname> is an implementation which
will load the authorities by searching the directory for groups of which the user is
a member (typically these will be <literal>groupOfNames</literal> or
<literal>groupOfUniqueNames</literal> entries in the directory). Consult the Javadoc
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
difference source (such as a database) then you can provide your own implementation
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
from the <quote>ou</quote> attribute of each match.</para>
<para>To configure a user search object, which uses the filter
<literal>(uid=&lt;user-login-name&gt;)</literal> for use instead of the
DN-pattern (or in addition to it), you would configure the following bean <programlisting><![CDATA[
<literal>(uid=&lt;user-login-name&gt;)</literal> for use instead of the DN-pattern
(or in addition to it), you would configure the following bean <programlisting><![CDATA[
<bean id="userSearch"
class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg index="0" value=""/>
@ -355,25 +346,25 @@
<interfacename>UserDetailsService</interfacename>, a common requirement is to be
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
<interfacename>UserDetails</interfacename> object is controlled by the
provider's <interfacename>UserDetailsContextMapper</interfacename> strategy, which
is responsible for mapping user objects to and from LDAP context data: <programlisting><![CDATA[
<interfacename>UserDetails</interfacename> object is controlled by the provider's
<interfacename>UserDetailsContextMapper</interfacename> strategy, which is
responsible for mapping user objects to and from LDAP context data: <programlisting><![CDATA[
public interface UserDetailsContextMapper {
UserDetails mapUserFromContext(DirContextOperations ctx, String username,
Collection<GrantedAuthority> authorities);
void mapUserToContext(UserDetails user, DirContextAdapter ctx);
}]]>
</programlisting> Only the first method is relevant for
authentication. If you provide an implementation of this interface, you can control
exactly how the UserDetails object is created. The first parameter is an instance of
Spring LDAP's <interfacename>DirContextOperations</interfacename> which gives you
access to the LDAP attributes which were loaded. The <literal>username</literal>
parameter is the name used to authenticate and the final parameter is the collection
of authorities loaded for the user. </para>
</programlisting> Only the first method is relevant for authentication. If you
provide an implementation of this interface, you can control exactly how the
UserDetails object is created. The first parameter is an instance of Spring LDAP's
<interfacename>DirContextOperations</interfacename> which gives you access to the
LDAP attributes which were loaded. The <literal>username</literal> parameter is the
name used to authenticate and the final parameter is the collection of authorities
loaded for the user. </para>
<para> The way the context data is loaded varies slightly depending on the type of
authentication you are using. With the <classname>BindAuthenticator</classname>,
the context returned from the bind operation will be used to read the attributes,
authentication you are using. With the <classname>BindAuthenticator</classname>, the
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
configured <interfacename>ContextSource</interfacename> (when a search is configured
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>
<title>Pre-Authentication Scenarios</title>
</info>
<para> There are situations where you want to use Spring Security for authorization, but the user
has already been reliably authenticated by some external system prior to accessing the
<para> There are situations where you want to use Spring Security for authorization, but 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.
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
<orderedlist><listitem><para>Identify the user making the request.
</para></listitem><listitem><para>Obtain the authorities for the
user.</para></listitem></orderedlist>The details will depend on the external authentication
mechanism. A user might be identified by their certificate information in the case of X.509, or
by an HTTP request 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>
application is running. When using pre-authentication, Spring Security has to <orderedlist>
<listitem>
<para>Identify the user making the request. </para>
</listitem>
<listitem>
<para>Obtain the authorities for the user.</para>
</listitem>
</orderedlist>The details will depend on the external authentication mechanism. A user might
be identified by their certificate information in the case of X.509, or by an HTTP request
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>
<title>Pre-Authentication Framework Classes</title>
<para> Because most pre-authentication mechanisms follow the same pattern, Spring Security has a
set of classes which provide an internal framework for implementing pre-authenticated
authentication providers. This removes duplication and allows new implementations to be added
in a structured fashion, without having to write everything from scratch. You don't need to
know about these classes if you want to use something like <link xlink:href="#x509">X.509
authentication</link>, as it already has a namespace configuration option which is simpler
to use and get started with. If you need to use explicit bean configuration or are planning on
writing your own implementation then an understanding of how the provided implementations work
will be useful. You will find classes under the
<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>
<para> Because most pre-authentication mechanisms follow the same pattern, Spring Security
has a set of classes which provide an internal framework for implementing
pre-authenticated authentication providers. This removes duplication and allows new
implementations to be added in a structured fashion, without having to write everything
from scratch. You don't need to know about these classes if you want to use something
like <link xlink:href="#x509">X.509 authentication</link>, as it already has a namespace
configuration option which is simpler to use and get started with. If you need to use
explicit bean configuration or are planning on writing your own implementation then an
understanding of how the provided implementations work will be useful. You will find
classes under the
<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>
<title>AbstractPreAuthenticatedProcessingFilter</title>
<para> This class will check the current contents of the security context and, if empty, it
will attempt to extract user information from the HTTP request and submit it to the
<interfacename>AuthenticationManager</interfacename>. Subclasses override the following
methods to obtain this information:
<para> This class will check the current contents of the security context and, if empty,
it will attempt to extract user information from the HTTP request and submit it to
the <interfacename>AuthenticationManager</interfacename>. Subclasses override the
following methods to obtain this information:
<programlisting language="java">
protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request);
protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request);
</programlisting>
After calling these, the filter will create a
<classname>PreAuthenticatedAuthenticationToken</classname> containing the returned data
and submit it for authentication. By <quote>authentication</quote> here, we really just mean
further processing to perhaps load the user's authorities, but the standard Spring Security
authentication architecture is followed. </para>
<classname>PreAuthenticatedAuthenticationToken</classname> containing the returned
data and submit it for authentication. By <quote>authentication</quote> here, we
really just mean further processing to perhaps load the user's authorities, but the
standard Spring Security authentication architecture is followed. </para>
</section>
<section>
<title>AbstractPreAuthenticatedAuthenticationDetailsSource</title>
<para> Like other Spring Security authentication filters, the pre-authentication filter has an
<literal>authenticationDetailsSource</literal> property which by default will create a
<classname>WebAuthenticationDetails</classname> object to store additional information
such as the session-identifier and originating IP address in the <literal>details</literal>
property of the <interfacename>Authentication</interfacename> object. In cases where user
role information can be obtained from the pre-authentication mechanism, the data is also
<para> Like other Spring Security authentication filters, the pre-authentication filter
has an <literal>authenticationDetailsSource</literal> property which by default will
create a <classname>WebAuthenticationDetails</classname> object to store additional
information such as the session-identifier and originating IP address in the
<literal>details</literal> property of the
<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
<classname>AbstractPreAuthenticatedAuthenticationDetailsSource</classname> use an extended
details object which implements the
<interfacename>GrantedAuthoritiesContainer</interfacename> interface, thus enabling the
authentication provider to read the authorities which were externally allocated to the user.
We'll look at a concrete example next. </para>
<classname>AbstractPreAuthenticatedAuthenticationDetailsSource</classname> use an
extended details object which implements the
<interfacename>GrantedAuthoritiesContainer</interfacename> interface, thus enabling
the authentication provider to read the authorities which were externally allocated
to the user. We'll look at a concrete example next. </para>
<section xml:id="j2ee-preauth-details">
<title>J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource</title>
<para> If the filter is configured with an <literal>authenticationDetailsSource</literal>
which is an instance of this class, the authority information is obtained by calling the
<methodname>isUserInRole(String role)</methodname> method for each of a pre-determined
set of <quote>mappable roles</quote>. The class gets these from a configured
<interfacename>MappableAttributesRetriever</interfacename>. Possible implementations
include hard-coding a list in the application context and reading the role information
from the <literal>&lt;security-role&gt;</literal> information in a
<filename>web.xml</filename> file. The pre-authentication sample application uses the
latter approach. </para>
<para>There is an additional stage where the roles (or attributes) are mapped to Spring
Security <interfacename>GrantedAuthority</interfacename> objects using a configured
<interfacename>Attributes2GrantedAuthoritiesMapper</interfacename>. The default will
just add the usual <literal>ROLE_</literal> prefix to the names, but it gives you full
control over the behaviour. </para>
<para> If the filter is configured with an
<literal>authenticationDetailsSource</literal> which is an instance of this
class, the authority information is obtained by calling the
<methodname>isUserInRole(String role)</methodname> method for each of a
pre-determined set of <quote>mappable roles</quote>. The class gets these from a
configured <interfacename>MappableAttributesRetriever</interfacename>. Possible
implementations include hard-coding a list in the application context and
reading the role information from the <literal>&lt;security-role&gt;</literal>
information in a <filename>web.xml</filename> file. The pre-authentication
sample application uses the latter approach. </para>
<para>There is an additional stage where the roles (or attributes) are mapped to
Spring Security <interfacename>GrantedAuthority</interfacename> objects using a
configured <interfacename>Attributes2GrantedAuthoritiesMapper</interfacename>.
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>
<title>PreAuthenticatedAuthenticationProvider</title>
<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
to a <interfacename>AuthenticationUserDetailsService</interfacename>. The latter is similar
to the standard <interfacename>UserDetailsService</interfacename> but takes an
<interfacename>Authentication</interfacename> object rather than just user name:
<interfacename>UserDetails</interfacename> object for the user. It does this by
delegating to a <interfacename>AuthenticationUserDetailsService</interfacename>. The
latter is similar to the standard <interfacename>UserDetailsService</interfacename>
but takes an <interfacename>Authentication</interfacename> object rather than just
user name:
<programlisting language="java">
public interface AuthenticationUserDetailsService {
UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException;
}
</programlisting>
This interface may have also other uses but with pre-authentication it allows access to the
authorities which were packaged in the <interfacename>Authentication</interfacename> object,
as we saw in the previous section. The
<classname>PreAuthenticatedGrantedAuthoritiesUserDetailsService</classname> class does
this. Alternatively, it may delegate to a standard
This interface may have also other uses but with pre-authentication it allows access
to the authorities which were packaged in the
<interfacename>Authentication</interfacename> object, as we saw in the previous
section. The
<classname>PreAuthenticatedGrantedAuthoritiesUserDetailsService</classname> class
does this. Alternatively, it may delegate to a standard
<interfacename>UserDetailsService</interfacename> via the
<classname>UserDetailsByNameServiceWrapper</classname> implementation. </para>
</section>
<section>
<title>Http403ForbiddenEntryPoint</title>
<para> The <interfacename>AuthenticationEntryPoint</interfacename> was discussed in the <link
xlink:href="#tech-intro-auth-entry-point">technical overview</link> chapter. Normally it
is responsible for kick-starting the authentication process for an unauthenticated user
(when they try to access a protected resource), but in the pre-authenticated case this
doesn't apply. You would only configure the
<classname>ExceptionTranslationFilter</classname> with an instance of this class if you
aren't using pre-authentication in combination with other authentication mechanisms. It will
be called if the user is rejected by the
<para> The <interfacename>AuthenticationEntryPoint</interfacename> was discussed in the
<link xlink:href="#tech-intro-auth-entry-point">technical overview</link> chapter.
Normally it is responsible for kick-starting the authentication process for an
unauthenticated user (when they try to access a protected resource), but in the
pre-authenticated case this doesn't apply. You would only configure the
<classname>ExceptionTranslationFilter</classname> with an instance of this class if
you aren't using pre-authentication in combination with other authentication
mechanisms. It will be called if the user is rejected by the
<classname>AbstractPreAuthenticatedProcessingFilter</classname> resulting in a null
authentication. It always returns a <literal>403</literal>-forbidden response code if
called. </para>
authentication. It always returns a <literal>403</literal>-forbidden response code
if called. </para>
</section>
</section>
<section>
<title>Concrete Implementations</title>
<para> X.509 authentication is covered in its <link xlink:href="#x509">own chapter</link>. Here
we'll look at some classes which provide support for other pre-authenticated scenarios. </para>
<para> X.509 authentication is covered in its <link xlink:href="#x509">own chapter</link>.
Here we'll look at some classes which provide support for other pre-authenticated
scenarios. </para>
<section>
<title>Request-Header Authentication (Siteminder)</title>
<para> An external authentication system may supply information to the application by setting
specific headers on the HTTP request. A well known example of this is Siteminder, which
passes the username in a header called <literal>SM_USER</literal>. This mechanism is
supported by the class <classname>RequestHeaderAuthenticationFilter</classname> which simply
extracts the 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>
<para> An external authentication system may supply information to the application by
setting specific headers on the HTTP request. A well known example of this is
Siteminder, which passes the username in a header called <literal>SM_USER</literal>.
This mechanism is supported by the class
<classname>RequestHeaderAuthenticationFilter</classname> which simply extracts the
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>
<para>Note that when using a system like this, the framework performs no authentication
checks at all and it is <emphasis>extremely</emphasis> important that the external system
is configured properly and protects all access to the application. If an attacker is able
to forge the headers in their original request without this being detected then they could
potentially choose any username they wished. </para>
<para>Note that when using a system like this, the framework performs no
authentication checks at all and it is <emphasis>extremely</emphasis> important
that the external system is configured properly and protects all access to the
application. If an attacker is able to forge the headers in their original
request without this being detected then they could potentially choose any
username they wished. </para>
</tip>
<section>
<title>Siteminder Example Configuration</title>
@ -162,27 +174,28 @@ class="org.springframework.security.web.authentication.preauth.PreAuthenticatedA
<security:authentication-provider ref="preauthAuthProvider" />
</security-authentication-manager>
]]>
</programlisting> We've assumed here that the security namespace is being used for
configuration (hence the user of the <literal>custom-filter</literal>,
</programlisting> We've assumed here that the security namespace is being used for configuration
(hence the user of the <literal>custom-filter</literal>,
<literal>authentication-manager</literal> and
<literal>custom-authentication-provider</literal> elements (you can read more about them
in the <link xlink:href="ns-config">namespace chapter</link>). You would leave these out
of a traditional bean configuration. It's also assumed that you have added a
<interfacename>UserDetailsService</interfacename> (called
<quote>userDetailsService</quote>) to your configuration to load the user's roles.
</para>
<literal>custom-authentication-provider</literal> elements (you can read more
about them in the <link xlink:href="ns-config">namespace chapter</link>). You
would leave these out of a traditional bean configuration. It's also assumed
that you have added a <interfacename>UserDetailsService</interfacename> (called
<quote>userDetailsService</quote>) to your configuration to load the user's
roles. </para>
</section>
</section>
<section>
<title>J2EE Container Authentication</title>
<para> The class <classname>J2eePreAuthenticatedProcessingFilter</classname> will extract the
username from the <literal>userPrincipal</literal> property of the
<interfacename>HttpServletRequest</interfacename>. Use of this filter would usually be
combined with the use of J2EE roles as described above in <xref
<para> The class <classname>J2eePreAuthenticatedProcessingFilter</classname> will
extract the username from the <literal>userPrincipal</literal> property of the
<interfacename>HttpServletRequest</interfacename>. Use of this filter would usually
be combined with the use of J2EE roles as described above in <xref
linkend="j2ee-preauth-details"/>. </para>
<para> There is a sample application in the codebase which uses this approach, so get hold of
the code from subversion and have a look at the application context file if you are
interested. The code is in the <filename>samples/preauth</filename> directory. </para>
<para> There is a sample application in the codebase which uses this approach, so get
hold of the code from subversion and have a look at the application context file if
you are interested. The code is in the <filename>samples/preauth</filename>
directory. </para>
</section>
</section>
</chapter>

View File

@ -15,10 +15,9 @@
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>
<para> Note that both implemementations require a
<interfacename>UserDetailsService</interfacename>. If you are using an
authentication provider which doesn't use a
<interfacename>UserDetailsService</interfacename> (for example, the LDAP provider)
then it won't work unless you also have a
<interfacename>UserDetailsService</interfacename>. If you are using an authentication
provider which doesn't use a <interfacename>UserDetailsService</interfacename> (for
example, the LDAP provider) then it won't work unless you also have a
<interfacename>UserDetailsService</interfacename> bean in your application context.
</para>
</section>
@ -63,12 +62,13 @@
<title>Persistent Token Approach</title>
<para>This approach is based on the article <link
xlink:href="http://jaspan.com/improved_persistent_login_cookie_best_practice"
>http://jaspan.com/improved_persistent_login_cookie_best_practice</link> with some
minor modifications <footnote><para>Essentially, the username is not included in the
cookie, to prevent exposing a valid login name unecessarily. There is a
discussion on this in the comments section of this article.</para></footnote>.
To use the this approach with namespace configuration, you would supply a datasource
reference: <programlisting><![CDATA[
>http://jaspan.com/improved_persistent_login_cookie_best_practice</link> with some minor
modifications <footnote>
<para>Essentially, the username is not included in the cookie, to prevent exposing a
valid login name unecessarily. There is a discussion on this in the comments section
of this article.</para>
</footnote>. To use the this approach with namespace configuration, you would supply a
datasource reference: <programlisting><![CDATA[
<http>
...
<remember-me data-source-ref="someDataSource"/>
@ -91,10 +91,10 @@
</info>
<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
<literal>UsernamePasswordAuthenticationFilter</literal>, and is implemented via
hooks in the <literal>AbstractAuthenticationProcessingFilter</literal> superclass. The
hooks will invoke a concrete <interfacename>RememberMeServices</interfacename> at the
appropriate times. The interface looks like this:
<literal>UsernamePasswordAuthenticationFilter</literal>, and is implemented via hooks in
the <literal>AbstractAuthenticationProcessingFilter</literal> superclass. The hooks will
invoke a concrete <interfacename>RememberMeServices</interfacename> at the appropriate
times. The interface looks like this:
<programlisting language="java">
Authentication autoLogin(HttpServletRequest request, HttpServletResponse response);
void loginFail(HttpServletRequest request, HttpServletResponse response);
@ -122,12 +122,12 @@
<literal>RememberMeAuthenticationProvider</literal>. A <literal>key</literal> is
shared between this authentication provider and the
<literal>TokenBasedRememberMeServices</literal>. In addition,
<literal>TokenBasedRememberMeServices</literal> requires A UserDetailsService
from which it can retrieve the username and password for signature comparison
purposes, and generate the <literal>RememberMeAuthenticationToken</literal> to
contain the correct <interfacename>GrantedAuthority</interfacename>[]s. Some sort of
logout command should be provided by the application that invalidates the cookie if
the user requests this. <classname>TokenBasedRememberMeServices</classname> also
<literal>TokenBasedRememberMeServices</literal> requires A UserDetailsService from
which it can retrieve the username and password for signature comparison purposes,
and generate the <literal>RememberMeAuthenticationToken</literal> to contain the
correct <interfacename>GrantedAuthority</interfacename>[]s. Some sort of logout
command should be provided by the application that invalidates the cookie if the
user requests this. <classname>TokenBasedRememberMeServices</classname> also
implements Spring Security's <interfacename>LogoutHandler</interfacename> interface
so can be used with <classname>LogoutFilter</classname> to have the cookie cleared
automatically. </para>
@ -162,14 +162,18 @@
<section>
<title>PersistentTokenBasedRememberMeServices</title>
<para> This class can be used in the same way as
<classname>TokenBasedRememberMeServices</classname>, but it additionally needs
to be configured with a <interfacename>PersistentTokenRepository</interfacename> to
store the tokens. There are two standard implementations.
<itemizedlist><listitem><para><classname>InMemoryTokenRepositoryImpl</classname>
which is intended for testing
only.</para></listitem><listitem><para><classname>JdbcTokenRepositoryImpl</classname>
which stores the tokens in a database. </para></listitem></itemizedlist>
The database schema is described above in <xref
<classname>TokenBasedRememberMeServices</classname>, but it additionally needs to be
configured with a <interfacename>PersistentTokenRepository</interfacename> to store
the tokens. There are two standard implementations. <itemizedlist>
<listitem>
<para><classname>InMemoryTokenRepositoryImpl</classname> which is intended for
testing only.</para>
</listitem>
<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>
</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">
<info><title>Overview</title></info>
<info>
<title>Overview</title>
</info>
<para>The <classname>AbstractSecurityInterceptor</classname> is able to
temporarily replace the <interfacename>Authentication</interfacename> object in
the <interfacename>SecurityContext</interfacename> and
<classname>SecurityContextHolder</classname> during the secure object
callback phase. This only occurs if the original
<interfacename>Authentication</interfacename> object was successfully processed by
the <interfacename>AuthenticationManager</interfacename> and
<interfacename>AccessDecisionManager</interfacename>. The
<para>The <classname>AbstractSecurityInterceptor</classname> is able to temporarily replace
the <interfacename>Authentication</interfacename> object in the
<interfacename>SecurityContext</interfacename> and
<classname>SecurityContextHolder</classname> during the secure object callback phase.
This only occurs if the original <interfacename>Authentication</interfacename> object
was successfully processed by the <interfacename>AuthenticationManager</interfacename>
and <interfacename>AccessDecisionManager</interfacename>. The
<literal>RunAsManager</literal> will indicate the replacement
<interfacename>Authentication</interfacename> object, if any, that should be used
during the <literal>SecurityInterceptorCallback</literal>.</para>
<interfacename>Authentication</interfacename> object, if any, that should be used during
the <literal>SecurityInterceptorCallback</literal>.</para>
<para>By temporarily replacing the <interfacename>Authentication</interfacename>
object during the secure object callback phase, the secured invocation
will be able to call other objects which require different
authentication and authorization credentials. It will also be able to
perform any internal security checks for specific
<para>By temporarily replacing the <interfacename>Authentication</interfacename> object
during the secure object callback phase, the secured invocation will be able to call
other objects which require different authentication and authorization credentials. It
will also be able to perform any internal security checks for specific
<interfacename>GrantedAuthority</interfacename> objects. Because Spring Security
provides a number of helper classes that automatically configure
remoting protocols based on the contents of the
<classname>SecurityContextHolder</classname>, these run-as replacements
are particularly useful when calling remote web services</para>
provides a number of helper classes that automatically configure remoting protocols
based on the contents of the <classname>SecurityContextHolder</classname>, these run-as
replacements are particularly useful when calling remote web services</para>
</section>
<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:
<programlisting>
Authentication buildRunAs(Authentication authentication, Object object,
List&lt;ConfigAttribute&gt; config);
boolean supports(ConfigAttribute attribute);
boolean supports(Class clazz);
</programlisting>
</para>
</programlisting> </para>
<para>The first method returns the <interfacename>Authentication</interfacename>
object that should replace the existing
<interfacename>Authentication</interfacename> object for the duration of the
method invocation. If the method returns <literal>null</literal>, it
indicates no replacement should be made. The second method is used by
the <classname>AbstractSecurityInterceptor</classname> as part of its
startup validation of configuration attributes. The
<literal>supports(Class)</literal> method is called by a security
interceptor implementation to ensure the configured
<literal>RunAsManager</literal> supports the type of secure object
that the security interceptor will present.</para>
<para>The first method returns the <interfacename>Authentication</interfacename> object that
should replace the existing <interfacename>Authentication</interfacename> object for the
duration of the method invocation. If the method returns <literal>null</literal>, it
indicates no replacement should be made. The second method is used by the
<classname>AbstractSecurityInterceptor</classname> as part of its startup validation of
configuration attributes. The <literal>supports(Class)</literal> method is called by a
security interceptor implementation to ensure the configured
<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>
is provided with Spring Security. The
<literal>RunAsManagerImpl</literal> class returns a replacement
<literal>RunAsUserToken</literal> if any
<literal>ConfigAttribute</literal> starts with
<literal>RUN_AS_</literal>. If any such
<literal>ConfigAttribute</literal> is found, the replacement
<literal>RunAsUserToken</literal> will contain the same principal,
<para>One concrete implementation of a <literal>RunAsManager</literal> is provided with
Spring Security. The <literal>RunAsManagerImpl</literal> class returns a replacement
<literal>RunAsUserToken</literal> if any <literal>ConfigAttribute</literal> starts with
<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
<interfacename>Authentication</interfacename> object, along with a new
<literal>GrantedAuthorityImpl</literal> for each
<literal>RUN_AS_</literal> <literal>ConfigAttribute</literal>. Each
new <literal>GrantedAuthorityImpl</literal> will be prefixed with
<literal>ROLE_</literal>, followed by the <literal>RUN_AS</literal>
<literal>ConfigAttribute</literal>. For example, a
<literal>GrantedAuthorityImpl</literal> for each <literal>RUN_AS_</literal>
<literal>ConfigAttribute</literal>. Each new <literal>GrantedAuthorityImpl</literal>
will be prefixed with <literal>ROLE_</literal>, followed by the
<literal>RUN_AS</literal> <literal>ConfigAttribute</literal>. For example, a
<literal>RUN_AS_SERVER</literal> will result in the replacement
<literal>RunAsUserToken</literal> containing a
<literal>ROLE_RUN_AS_SERVER</literal> granted authority.</para>
<literal>RunAsUserToken</literal> containing a <literal>ROLE_RUN_AS_SERVER</literal>
granted authority.</para>
<para>The replacement <literal>RunAsUserToken</literal> is just like
any other <interfacename>Authentication</interfacename> object. It needs to be
authenticated by the <interfacename>AuthenticationManager</interfacename>,
probably via delegation to a suitable
<classname>AuthenticationProvider</classname>. The
<literal>RunAsImplAuthenticationProvider</literal> performs such
authentication. It simply accepts as valid any
<literal>RunAsUserToken</literal> presented.</para>
<para>The replacement <literal>RunAsUserToken</literal> is just like any other
<interfacename>Authentication</interfacename> object. It needs to be authenticated by
the <interfacename>AuthenticationManager</interfacename>, probably via delegation to a
suitable <classname>AuthenticationProvider</classname>. The
<literal>RunAsImplAuthenticationProvider</literal> performs such authentication. It
simply accepts as valid any <literal>RunAsUserToken</literal> presented.</para>
<para>To ensure malicious code does not create a
<literal>RunAsUserToken</literal> and present it for guaranteed
acceptance by the <literal>RunAsImplAuthenticationProvider</literal>,
the hash of a key is stored in all generated tokens. The
<literal>RunAsManagerImpl</literal> and
<literal>RunAsImplAuthenticationProvider</literal> is created in the
bean context with the same key:
<programlisting>
<para>To ensure malicious code does not create a <literal>RunAsUserToken</literal> and
present it for guaranteed acceptance by the
<literal>RunAsImplAuthenticationProvider</literal>, the hash of a key is stored in all
generated tokens. The <literal>RunAsManagerImpl</literal> and
<literal>RunAsImplAuthenticationProvider</literal> is created in the bean context with
the same key: <programlisting>
<![CDATA[
<bean id="runAsManager"
class="org.springframework.security.access.intercept.RunAsManagerImpl">
@ -97,10 +89,9 @@
class="org.springframework.security.access.intercept.RunAsImplAuthenticationProvider">
<property name="key" value="my_run_as_password"/>
</bean>]]></programlisting></para>
<para>By using the same key, each <literal>RunAsUserToken</literal>
can be validated it was created by an approved
<literal>RunAsManagerImpl</literal>. The
<literal>RunAsUserToken</literal> is immutable after creation for
security reasons</para>
<para>By using the same key, each <literal>RunAsUserToken</literal> can be validated it was
created by an approved <literal>RunAsManagerImpl</literal>. The
<literal>RunAsUserToken</literal> is immutable after creation for security
reasons</para>
</section>
</chapter>

View File

@ -10,22 +10,22 @@
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
<link xlink:href="http://www.springsource.org/security/">
http://www.springsource.org/security/ </link> if you need it. All paths referred to in
this chapter are relative to the project source directory. </para>
http://www.springsource.org/security/ </link> if you need it. All paths referred to in this
chapter are relative to the project source directory. </para>
<section xml:id="tutorial-sample">
<title>Tutorial Sample</title>
<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
distribution zip file, ready to be deployed into your web container
(<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
in combination with the commonly-used <link xlink:href="#remember-me">remember-me</link>
xlink:href="#ns-form-and-basic">form-based</link> authentication mechanism is used in
combination with the commonly-used <link xlink:href="#remember-me">remember-me</link>
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
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
basic integration is achieved do we suggest you attempt adding in method authorization
or domain object security.</para>
<literal>web.xml</literal> entries) to your existing application. Only when this basic
integration is achieved do we suggest you attempt adding in method authorization or
domain object security.</para>
</section>
<section xml:id="contacts-sample">
<title>Contacts</title>
@ -35,11 +35,11 @@
administer a simple database of contacts (the domain objects).</para>
<para>To deploy, simply copy the WAR file from Spring Security distribution into your
containers <literal>webapps</literal> directory. The war should be called
<filename>spring-security-samples-contacts-3.0.x.war</filename> (the appended
version number will vary depending on what release you are using). </para>
<filename>spring-security-samples-contacts-3.0.x.war</filename> (the appended version
number will vary depending on what release you are using). </para>
<para>After starting your container, check the application can load. Visit
<literal>http://localhost:8080/contacts</literal> (or whichever URL is appropriate
for your web container and the WAR you deployed). </para>
<literal>http://localhost:8080/contacts</literal> (or whichever URL is appropriate for
your web container and the WAR you deployed). </para>
<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
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
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
<literal>ROLE_SUPERVISOR</literal> are granted access to delete their contacts.
Behind the scenes, the <classname>MethodSecurityInterceptor</classname> is securing the
<literal>ROLE_SUPERVISOR</literal> are granted access to delete their contacts. Behind
the scenes, the <classname>MethodSecurityInterceptor</classname> is securing the
business objects. </para>
<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
@ -103,12 +103,12 @@ Success! Your web filters appear to be properly configured!
<title>CAS Sample</title>
<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
<link xlink:href="get-source">the introduction</link>. You'll find the relevant
files 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
server and the client directly from the source tree, complete with SSL support. You have
to download the CAS Server web application (a war file) from the CAS site and drop it
into the <filename>samples/cas/server</filename> directory. </para>
<link xlink:href="get-source">the introduction</link>. You'll find the relevant files
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 server
and the client directly from the source tree, complete with SSL support. You have to
download the CAS Server web application (a war file) from the CAS site and drop it into
the <filename>samples/cas/server</filename> directory. </para>
</section>
<section xml:id="preauth-sample">
<title>Pre-Authentication Sample</title>

View File

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

View File

@ -4,29 +4,29 @@
<title>The Security Filter Chain</title>
</info>
<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
it has no strong links to any particular web technology. It deals in
<classname>HttpServletRequest</classname>s and <classname>HttpServletResponse</classname>s and
doesn't care whether the requests come from a browser, a web service client, an
doesn't use servlets or any other servlet-based frameworks (such as Spring MVC) internally,
so it has no strong links to any particular web technology. It deals in
<classname>HttpServletRequest</classname>s and <classname>HttpServletResponse</classname>s
and doesn't care whether the requests come 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
particular responsibility and filters are added or removed from the configuration depending on
which services are required. The ordering of the filters is important as there are 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
to define any Spring beans explicitly but here may be times when you want full control over the
security filter 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>
particular responsibility and filters are added or removed from the configuration depending
on which services are required. The ordering of the filters is important as there are
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 to define any Spring beans explicitly but here may be times when you want full control
over the security filter 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">
<title><classname>DelegatingFilterProxy</classname></title>
<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
Security, the filter classes are also Spring beans defined in the application context and thus
able to take advantage of Spring's rich dependency-injection facilities and lifecycle
interfaces. Spring's <classname>DelegatingFilterProxy</classname> provides the link between
<filename>web.xml</filename> and the application context. </para>
<para>When using <classname>DelegatingFilterProxy</classname>, you will see something like this
in the <filename>web.xml</filename> file: <programlisting><![CDATA[
<filename>web.xml</filename>, or they will be ignored by the servlet container. In
Spring Security, the filter classes are also Spring beans defined in the application
context and thus able to take advantage of Spring's rich dependency-injection facilities
and lifecycle interfaces. Spring's <classname>DelegatingFilterProxy</classname> provides
the link between <filename>web.xml</filename> and the application context. </para>
<para>When using <classname>DelegatingFilterProxy</classname>, you will see something like
this in the <filename>web.xml</filename> file: <programlisting><![CDATA[
<filter>
<filter-name>myFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
@ -37,29 +37,29 @@
<url-pattern>/*</url-pattern>
</filter-mapping>]]>
</programlisting> Notice that the filter is actually a
<literal>DelegatingFilterProxy</literal>, and not the class that will actually implement the
logic of the filter. What <classname>DelegatingFilterProxy</classname> does is delegate the
<interfacename>Filter</interfacename>'s methods through to a bean which is obtained from the
Spring application context. This enables the bean to benefit from the Spring web application
context lifecycle support and configuration flexibility. The bean must implement
<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
<literal>DelegatingFilterProxy</literal>, and not the class that will actually implement
the logic of the filter. What <classname>DelegatingFilterProxy</classname> does is
delegate the <interfacename>Filter</interfacename>'s methods through to a bean which is
obtained from the Spring application context. This enables the bean to benefit from the
Spring web application context lifecycle support and configuration flexibility. The bean
must implement <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>
</section>
<section xml:id="filter-chain-proxy">
<title><classname>FilterChainProxy</classname></title>
<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
<classname>DelegatingFilterProxy</classname> entry to <filename>web.xml</filename> for each
filter, making sure that they are ordered correctly. This is a cumbersome approach and
clutters up the <filename>web.xml</filename> file quickly if we have a lot of filters. We
would prefer to just add a single entry to <filename>web.xml</filename> and deal entirely with
the application context file for managing our web security beans. This is where Spring
Secuiryt's <classname>FilterChainProxy</classname> comes in. It is wired using a
<literal>DelegatingFilterProxy</literal>, just like in the example above, but with the
<literal>filter-name</literal> set to the bean name <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[
<classname>DelegatingFilterProxy</classname> entry to <filename>web.xml</filename> for
each filter, making sure that they are ordered correctly. This is a cumbersome approach
and clutters up the <filename>web.xml</filename> file quickly if we have a lot of
filters. We would prefer to just add a single entry to <filename>web.xml</filename> and
deal entirely with the application context file for managing our web security beans.
This is where Spring Secuirity's <classname>FilterChainProxy</classname> comes in. It is
wired using a <literal>DelegatingFilterProxy</literal>, just like in the example above,
but with the <literal>filter-name</literal> set to the bean name
<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">
<sec:filter-chain-map path-type="ant">
<sec:filter-chain pattern="/webServices/**" filters="
@ -75,104 +75,114 @@
</sec:filter-chain-map>
</bean>
]]>
</programlisting> The namespace element <literal>filter-chain-map</literal> is used
to set 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 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 names specified in the
<literal>filters</literal> element. Both regular expressions 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
current web request and the list of filter beans specified by the <literal>filters</literal>
attribute will be applied to that request. The filters will be invoked in the order they are
defined, so you have complete control over the filter chain which is applied to a particular
URL.</para>
</programlisting> The namespace element <literal>filter-chain-map</literal> is used to set
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 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 names specified in the <literal>filters</literal> element. Both regular expressions
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 current web request and the list of filter beans specified by the
<literal>filters</literal> attribute will be applied to that request. The filters will
be invoked in the order they are defined, so you have complete control over the filter
chain which is applied to a particular URL.</para>
<para>You may have noticed we have declared two
<classname>SecurityContextPersistenceFilter</classname>s in the filter chain
(<literal>ASC</literal> is short for <literal>allowSessionCreation</literal>, a property of
<classname>SecurityContextPersistenceFilter</classname>). As web services will never present
a <literal>jsessionid</literal> on future requests, creating <literal>HttpSession</literal>s
for such user agents would be wasteful. If you had a high-volume application which required
maximum scalability, we recommend you use the approach shown above. For smaller applications,
using a single <classname>SecurityContextPersistenceFilter</classname> (with its default
(<literal>ASC</literal> is short for <literal>allowSessionCreation</literal>, a property
of <classname>SecurityContextPersistenceFilter</classname>). As web services will never
present a <literal>jsessionid</literal> on future requests, creating
<literal>HttpSession</literal>s for such user agents would be wasteful. If you had a
high-volume application which required maximum scalability, we recommend you use the
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
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"
>namespace configuration</link>, we used a <literal>DelegatingFilterProxy</literal> with the
name <quote>springSecurityFilterChain</quote>. You should now be able to see that this is the
name of the <classname>FilterChainProxy</classname> which is created by the namespace. </para>
>namespace configuration</link>, we used a <literal>DelegatingFilterProxy</literal> with
the name <quote>springSecurityFilterChain</quote>. You should now be able to see that
this is the name of the <classname>FilterChainProxy</classname> which is created by the
namespace. </para>
<section>
<title>Bypassing the Filter Chain</title>
<para> As with the namespace, you can use the attribute <literal>filters = "none"</literal> as
an alternative to supplying a filter bean list. This will omit the request pattern from the
security filter chain entirely. Note that anything matching this path will then have no
authentication or authorization services applied and will be freely accessible. If you want
to make use of the contents of the <classname>SecurityContext</classname> contents during a
request, then it must have passed through the security filter chain. Otherwise the
<classname>SecurityContextHolder</classname> will not have been populated and the contents
will be null.</para>
<para> As with the namespace, you can use the attribute <literal>filters =
"none"</literal> as an alternative to supplying a filter bean list. This will omit
the request pattern from the security filter chain entirely. Note that anything
matching this path will then have no authentication or authorization services
applied and will be freely accessible. If you want to make use of the contents of
the <classname>SecurityContext</classname> contents during a request, then it must
have passed through the security filter chain. Otherwise the
<classname>SecurityContextHolder</classname> will not have been populated and the
contents will be null.</para>
</section>
</section>
<section>
<title>Filter Ordering</title>
<para>The order that filters are defined in the chain is very important. Irrespective of which
filters you are actually using, the order should be as follows:
<orderedlist><listitem><para><classname>ChannelProcessingFilter</classname>, because
it might need to redirect to a different
protocol</para></listitem><listitem><para><classname>ConcurrentSessionFilter</classname>,
because it doesn't use any <classname>SecurityContextHolder</classname> functionality
but needs to update the <interfacename>SessionRegistry</interfacename> to reflect
ongoing requests from the
principal</para></listitem><listitem><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 -
<para>The order that filters are defined in the chain is very important. Irrespective of
which filters you are actually using, the order should be as follows: <orderedlist>
<listitem>
<para><classname>ChannelProcessingFilter</classname>, because it might need to
redirect to a different protocol</para>
</listitem>
<listitem>
<para><classname>ConcurrentSessionFilter</classname>, because it doesn't use any
<classname>SecurityContextHolder</classname> functionality but needs to update
the <interfacename>SessionRegistry</interfacename> to reflect ongoing requests
from the principal</para>
</listitem>
<listitem>
<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>CasAuthenticationFilter</classname>,
<classname>BasicAuthenticationFilter</classname> etc - so that the
<classname>SecurityContextHolder</classname> can be modified to contain a valid
<interfacename>Authentication</interfacename> request
token</para></listitem><listitem><para>The
<literal>SecurityContextHolderAwareRequestFilter</literal>, if you are using it to
install a Spring Security aware <literal>HttpServletRequestWrapper</literal> into your
servlet
container</para></listitem><listitem><para><classname>RememberMeAuthenticationFilter</classname>,
so that if no earlier authentication processing mechanism updated the
<classname>SecurityContextHolder</classname>, and the request presents a cookie 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
<interfacename>Authentication</interfacename> request token</para>
</listitem>
<listitem>
<para>The <literal>SecurityContextHolderAwareRequestFilter</literal>, if you are
using it to install a Spring Security aware
<literal>HttpServletRequestWrapper</literal> into your servlet container</para>
</listitem>
<listitem>
<para><classname>RememberMeAuthenticationFilter</classname>, so that if no earlier
authentication processing mechanism updated the
<classname>SecurityContextHolder</classname>, and the request presents a cookie
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
<interfacename>Authentication</interfacename> object will be put
there</para></listitem><listitem><para><classname>ExceptionTranslationFilter</classname>,
to catch any Spring Security exceptions so that either an HTTP error response can be
returned or an appropriate <interfacename>AuthenticationEntryPoint</interfacename> can
be
launched</para></listitem><listitem><para><classname>FilterSecurityInterceptor</classname>,
to protect web URIs and raise exceptions when access is
denied</para></listitem></orderedlist></para>
<interfacename>Authentication</interfacename> object will be put there</para>
</listitem>
<listitem>
<para><classname>ExceptionTranslationFilter</classname>, to catch any Spring
Security exceptions so that either an HTTP error response can be returned or an
appropriate <interfacename>AuthenticationEntryPoint</interfacename> can be
launched</para>
</listitem>
<listitem>
<para><classname>FilterSecurityInterceptor</classname>, to protect web URIs and
raise exceptions when access is denied</para>
</listitem>
</orderedlist></para>
</section>
<section>
<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
that the Spring Security filters come first. This enables the
<classname>SecurityContextHolder</classname> to be populated in time for use by the other
filters. Examples are the use of SiteMesh to decorate your web pages or a web framework like
Wicket which uses a filter to handle its requests. </para>
<para>If you're using some other framework that is also filter-based, then you need to 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 filters. Examples are the use of SiteMesh to decorate your web pages or a web
framework like Wicket which uses a filter to handle its requests. </para>
</section>
<!--
<section xml:id="taglib">

View File

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

View File

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

View File

@ -17,12 +17,12 @@
<para>The legacy options from Spring Security 2.0 are also supported, but
discouraged.</para>
</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.
The expression evaluation will be delegated to the
<interfacename>WebSecurityExpressionHandler</interfacename> defined in the
application context (you should have web expressions enabled in your
<literal>&lt;http></literal> namespace configuration to make sure this service is
available). So, for example, you might
expression</link>, specified in the <literal>access</literal> attribute of the tag. The
expression evaluation will be delegated to the
<interfacename>WebSecurityExpressionHandler</interfacename> defined in the application
context (you should have web expressions enabled in your <literal>&lt;http></literal>
namespace configuration to make sure this service is available). So, for example, you
might
have<programlisting>&lt;sec:authorize access="hasRole('supervisor')">
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
<interfacename>Authentication</interfacename> is an instance of Spring Security's
<interfacename>UserDetails</interfacename> object, then using
<literal>&lt;sec:authentication property="principal.username" /></literal> will
render the name of the current user.</para>
<literal>&lt;sec:authentication property="principal.username" /></literal> will render
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
prefer to keep as little logic as possible in the view. You can access the
<interfacename>Authentication</interfacename> object in your MVC controller (by
calling <code>SecurityContextHolder.getContext().getAuthentication()</code>) and add the
data directly to your model for rendering by the view.</para>
<interfacename>Authentication</interfacename> object in your MVC controller (by calling
<code>SecurityContextHolder.getContext().getAuthentication()</code>) and add the data
directly to your model for rendering by the view.</para>
</section>
<section>
<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>
<para>The permissions are passed to the <interfacename>PermissionFactory</interfacename>
defined in the application context, converting them to ACL
<interfacename>Permission</interfacename> instances, so they may be any format which
is supported by the factory - they don't have to be integers, they could be strings like
<interfacename>Permission</interfacename> instances, so they may be any format which is
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
<interfacename>PermissionFactory</interfacename> is found, an instance of
<classname>DefaultPermissionFactory</classname> will be used. The
<interfacename>AclService</interfacename>from the application context will be used
to load the <interfacename>Acl</interfacename> instance for the supplied object. The
<interfacename>AclService</interfacename>from the application context will be used to
load the <interfacename>Acl</interfacename> instance for the supplied object. The
<interfacename>Acl</interfacename> will be invoked with the required permissions to
check if any of them are granted.</para>
</section>

File diff suppressed because it is too large Load Diff

View File

@ -7,29 +7,32 @@
<section xml:id="filters">
<title>The Security Filter Chain</title>
<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
it has no strong links to any particular web technology. It deals in
<classname>HttpServletRequest</classname>s and <classname>HttpServletResponse</classname>s
and doesn't care whether the requests come from a browser, a web service client, an
<classname>HttpInvoker</classname> or an AJAX application. </para>
doesn't use servlets or any other servlet-based frameworks (such as Spring MVC)
internally, so it has no strong links to any particular web technology. It deals in
<classname>HttpServletRequest</classname>s and
<classname>HttpServletResponse</classname>s and doesn't care whether the requests come
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
particular responsibility and filters are added or removed from the configuration depending on
which services are required. The ordering of the filters is important as there are
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 to define any Spring beans explicitly but here may be times when you want full control
over the security filter 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>
particular responsibility and filters are added or removed from the configuration
depending on which services are required. The ordering of the filters is important as
there are 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 to define any Spring beans
explicitly but here may be times when you want full control over the security filter
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">
<title><classname>DelegatingFilterProxy</classname></title>
<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
Security, the filter classes are also Spring beans defined in the application context and
thus able to take advantage of Spring's rich dependency-injection facilities and lifecycle
interfaces. Spring's <classname>DelegatingFilterProxy</classname> provides the link between
<filename>web.xml</filename>, or they will be ignored by the servlet container. In
Spring Security, the filter classes are also Spring beans defined in the application
context and thus able to take advantage of Spring's rich dependency-injection
facilities and lifecycle interfaces. Spring's
<classname>DelegatingFilterProxy</classname> provides the link between
<filename>web.xml</filename> and the application context. </para>
<para>When using <classname>DelegatingFilterProxy</classname>, you will see something like
this in the <filename>web.xml</filename> file: <programlisting><![CDATA[
<para>When using <classname>DelegatingFilterProxy</classname>, you will see something
like this in the <filename>web.xml</filename> file: <programlisting><![CDATA[
<filter>
<filter-name>myFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
@ -40,29 +43,31 @@
<url-pattern>/*</url-pattern>
</filter-mapping>]]>
</programlisting> Notice that the filter is actually a
<literal>DelegatingFilterProxy</literal>, and not the class that will actually implement
the logic of the filter. What <classname>DelegatingFilterProxy</classname> does is delegate
the <interfacename>Filter</interfacename>'s methods through to a bean which is obtained from
the Spring application context. This enables the bean to benefit from the Spring web
application context lifecycle support and configuration flexibility. The bean must implement
<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
<literal>DelegatingFilterProxy</literal>, and not the class that will actually
implement the logic of the filter. What <classname>DelegatingFilterProxy</classname>
does is delegate the <interfacename>Filter</interfacename>'s methods through to a
bean which is obtained from the Spring application context. This enables the bean to
benefit from the Spring web application context lifecycle support and configuration
flexibility. The bean must implement
<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>
</section>
<section xml:id="filter-chain-proxy">
<title><classname>FilterChainProxy</classname></title>
<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
<classname>DelegatingFilterProxy</classname> entry to <filename>web.xml</filename> for
each filter, making sure that they are ordered correctly. This is a cumbersome approach and
clutters up the <filename>web.xml</filename> file quickly if we have a lot of filters. We
would prefer to just add a single entry to <filename>web.xml</filename> and deal entirely
with the application context file for managing our web security beans. This is where Spring
Secuiryt's <classname>FilterChainProxy</classname> comes in. It is wired using a
<literal>DelegatingFilterProxy</literal>, just like in the example above, but with the
<literal>filter-name</literal> set to the bean name <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[
<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
<classname>DelegatingFilterProxy</classname> entry to <filename>web.xml</filename>
for each filter, making sure that they are ordered correctly. This is a cumbersome
approach and clutters up the <filename>web.xml</filename> file quickly if we have a
lot of filters. We would prefer to just add a single entry to
<filename>web.xml</filename> and deal entirely with the application context file for
managing our web security beans. This is where Spring Secuiryt's
<classname>FilterChainProxy</classname> comes in. It is wired using a
<literal>DelegatingFilterProxy</literal>, just like in the example above, but with
the <literal>filter-name</literal> set to the bean name
<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">
<sec:filter-chain-map path-type="ant">
<sec:filter-chain pattern="/webServices/**" filters="
@ -78,127 +83,134 @@
</sec:filter-chain-map>
</bean>
]]>
</programlisting> The namespace element <literal>filter-chain-map</literal> is
used to set 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
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
names specified in the <literal>filters</literal> element. Both regular expressions 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
current web request and the list of filter beans specified by the <literal>filters</literal>
attribute will be applied to that request. The filters will be invoked in the order they are
defined, so you have complete control over the filter chain which is applied to a particular
URL.</para>
</programlisting> The namespace element <literal>filter-chain-map</literal> is used to set
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 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 names specified in the <literal>filters</literal> element. Both regular
expressions 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 current web request and the list of filter beans specified
by the <literal>filters</literal> attribute will be applied to that request. The
filters will be invoked in the order they are defined, so you have complete control
over the filter chain which is applied to a particular URL.</para>
<para>You may have noticed we have declared two
<classname>SecurityContextPersistenceFilter</classname>s in the filter chain
(<literal>ASC</literal> is short for <literal>allowSessionCreation</literal>, a property
of <classname>SecurityContextPersistenceFilter</classname>). As web services will never
present a <literal>jsessionid</literal> on future requests, creating
<literal>HttpSession</literal>s for such user agents would be wasteful. If you had a
high-volume application which required maximum scalability, we recommend you use the
approach shown above. For smaller applications, using a single
(<literal>ASC</literal> is short for <literal>allowSessionCreation</literal>, a
property of <classname>SecurityContextPersistenceFilter</classname>). As web
services will never present a <literal>jsessionid</literal> on future requests,
creating <literal>HttpSession</literal>s for such user agents would be wasteful. If
you had a high-volume application which required maximum scalability, we recommend
you use the 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
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>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="#namespace-auto-config">namespace configuration</link>, we used a
<literal>DelegatingFilterProxy</literal> with the name
<quote>springSecurityFilterChain</quote>. You should now be able to see that this is the
name of the <classname>FilterChainProxy</classname> which is created by the namespace. </para>
<quote>springSecurityFilterChain</quote>. You should now be able to see that this is
the name of the <classname>FilterChainProxy</classname> which is created by the
namespace. </para>
<section>
<title>Bypassing the Filter Chain</title>
<para> As with the namespace, you can use the attribute <literal>filters = "none"</literal>
as an alternative to supplying a filter bean list. This will omit the request pattern from
the security filter chain entirely. Note that anything matching this path will then have
no authentication or authorization services applied and will be freely accessible. If you
want to make use of the contents of the <classname>SecurityContext</classname> contents
during a request, then it must have passed through the security filter chain. Otherwise
the <classname>SecurityContextHolder</classname> will not have been populated and the
contents will be null.</para>
<para> As with the namespace, you can use the attribute <literal>filters =
"none"</literal> as an alternative to supplying a filter bean list. This will
omit the request pattern from the security filter chain entirely. Note that
anything matching this path will then have no authentication or authorization
services applied and will be freely accessible. If you want to make use of the
contents of the <classname>SecurityContext</classname> contents during a
request, then it must have passed through the security filter chain. Otherwise
the <classname>SecurityContextHolder</classname> will not have been populated
and the contents will be null.</para>
</section>
</section>
<section>
<title>Filter Ordering</title>
<para>The order that filters are defined in the chain is very important. Irrespective of which
filters you are actually using, the order should be as follows:
<orderedlist>
<para>The order that filters are defined in the chain is very important. Irrespective of
which filters you are actually using, the order should be as follows: <orderedlist>
<listitem>
<para><classname>ChannelProcessingFilter</classname>, because it might need to redirect
to a different protocol</para>
<para><classname>ChannelProcessingFilter</classname>, because it might need to
redirect to a different protocol</para>
</listitem>
<listitem>
<para><classname>ConcurrentSessionFilter</classname>, because it doesn't use any
<classname>SecurityContextHolder</classname> functionality but needs to update the
<interfacename>SessionRegistry</interfacename> to reflect ongoing requests from the
principal</para>
<classname>SecurityContextHolder</classname> functionality but needs to
update the <interfacename>SessionRegistry</interfacename> to reflect ongoing
requests from the principal</para>
</listitem>
<listitem>
<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>
<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>CasProcessingFilter</classname>,
<classname>BasicProcessingFilter</classname> etc - so that the
<classname>SecurityContextHolder</classname> can be modified to contain a valid
<interfacename>Authentication</interfacename> request token</para>
<classname>SecurityContextHolder</classname> can be modified to contain a
valid <interfacename>Authentication</interfacename> request token</para>
</listitem>
<listitem>
<para>The <literal>SecurityContextHolderAwareRequestFilter</literal>, if you are using
it to install a Spring Security aware <literal>HttpServletRequestWrapper</literal>
into your servlet container</para>
<para>The <literal>SecurityContextHolderAwareRequestFilter</literal>, if you are
using it to install a Spring Security aware
<literal>HttpServletRequestWrapper</literal> into your servlet
container</para>
</listitem>
<listitem>
<para><classname>RememberMeProcessingFilter</classname>, so that if no earlier
authentication processing mechanism updated the
<classname>SecurityContextHolder</classname>, and the request presents a cookie that
enables remember-me services to take place, a suitable remembered
<interfacename>Authentication</interfacename> object will be put there</para>
<classname>SecurityContextHolder</classname>, and the request presents a
cookie that enables remember-me services to take place, a suitable
remembered <interfacename>Authentication</interfacename> object will be put
there</para>
</listitem>
<listitem>
<para><classname>AnonymousProcessingFilter</classname>, so that if no earlier
authentication processing mechanism updated the
<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>
<para><classname>ExceptionTranslationFilter</classname>, to catch any Spring Security
exceptions so that either an HTTP error response can be returned or an appropriate
<interfacename>AuthenticationEntryPoint</interfacename> can be launched</para>
<para><classname>ExceptionTranslationFilter</classname>, to catch any Spring
Security exceptions so that either an HTTP error response can be returned or
an appropriate <interfacename>AuthenticationEntryPoint</interfacename> can
be launched</para>
</listitem>
<listitem>
<para><classname>FilterSecurityInterceptor</classname>, to protect web URIs and raise
exceptions when access is denied</para>
<para><classname>FilterSecurityInterceptor</classname>, to protect web URIs and
raise exceptions when access is denied</para>
</listitem>
</orderedlist></para>
</section>
<section>
<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 that the Spring Security filters come first. This enables the
<classname>SecurityContextHolder</classname> to be populated in time for use by the other
filters. Examples are the use of SiteMesh to decorate your web pages or a web framework like
Wicket which uses a filter to handle its requests. </para>
<para>If you're using some other framework that is also filter-based, then you need to
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 filters. Examples are the use of SiteMesh to decorate your web pages or a web
framework like Wicket which uses a filter to handle its requests. </para>
</section>
</section>
<!--
<!--
<section xml:id="taglib">
<info>
<title>Tag Libraries</title>

View File

@ -1,7 +1,12 @@
<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
of a server when using SSL, most commonly when using HTTPS from a browser. The browser
@ -10,37 +15,46 @@
maintains.</para>
<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
will authenticate the client by checking that its certificate is signed by an
acceptable authority. If a valid certificate has been provided, it can be obtained
through the servlet API in an application. Spring Security X.509 module extracts the
certificate using a filter. It maps the certificate to an application user and loads that
user's set of granted authorities for use with the standard Spring Security infrastructure.</para>
will authenticate the client by checking that its certificate is signed by an acceptable
authority. If a valid certificate has been provided, it can be obtained through the
servlet API in an application. Spring Security X.509 module extracts the certificate
using a filter. It maps the certificate to an application user and loads that user's set
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
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
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 get this working before trying it out with Spring Security</para>
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
get this working before trying it out with Spring Security</para>
</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;x509 subject-principal-regex="CN=(.*?)," user-service-ref="userService"/&gt;
...
&lt;/http&gt;
</programlisting> The element has two optional attributes: <itemizedlist>
</programlisting>
The element has two optional attributes: <itemizedlist>
<listitem>
<para><literal>subject-principal-regex</literal>. The regular expression used to
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
user.</para>
shown above. This is the username which will be passed to the
<interfacename>UserDetailsService</interfacename> to load the authorities for
the user.</para>
</listitem>
<listitem>
<para><literal>user-service-ref</literal>. This is the bean Id of the
<interfacename>UserDetailsService</interfacename> to be used with X.509.
It isn't needed if there is only one defined in your application
context.</para>
<interfacename>UserDetailsService</interfacename> to be used with X.509. It
isn't needed if there is only one defined in your application context.</para>
</listitem>
</itemizedlist> The <literal>subject-principal-regex</literal> should contain a single
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>
</section>
<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
<filename>samples/certificate</filename> directory in the Spring Security project.
You can use these to enable SSL for testing if you don't want to generate your own. The file
<filename>samples/certificate</filename> directory in the Spring Security project. You
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
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
SSL client authentication.
</para>
<para>
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
for the users from the sample applications. You can install these in your browser to
enable SSL client authentication. </para>
<para> 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
<programlisting>
&lt;Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" scheme="https" secure="true"
@ -77,10 +91,10 @@
truststoreType="JKS" truststorePass="password"
/&gt;
</programlisting>
<parameter>clientAuth</parameter> can also be set to <parameter>want</parameter> if you still
want SSL connections to succeed even if the client doesn't provide a certificate.
<parameter>clientAuth</parameter> can also be set to <parameter>want</parameter> if you
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
Spring Security unless you use a non-X.509 authentication mechanism, such as form authentication.
</para>
Spring Security unless you use a non-X.509 authentication mechanism, such as form
authentication. </para>
</section>
</chapter>