spring-security/docs/manual/src/docbook/namespace-config.xml
2009-10-08 14:14:40 +00:00

694 lines
45 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="ns-config"
xmlns:xlink="http://www.w3.org/1999/xlink">
<info>
<title>Security Namespace Configuration</title>
</info>
<section>
<title>Introduction</title>
<para> Namespace configuration has been available since version 2.0 of the Spring framework. It
allows you to supplement the traditional Spring beans application context syntax with elements
from additional XML schema. You can find more information in the Spring <link
xlink:href="http://static.springframework.org/spring/docs/2.5.x/reference/xsd-config.html">
Reference Documentation</link>. A namespace element can be used simply to allow a more
concise way of configuring an individual bean or, more powerfully, to define an alternative
configuration syntax which more closely matches the problem domain and hides the underlying
complexity from the user. A simple element may conceal the fact that multiple beans and
processing steps are being added to the application context. For example, adding the following
element from the security namespace to an application context will start up an embedded LDAP
server for testing use within the application: <programlisting><![CDATA[
<security:ldap-server />
]]></programlisting> This is much simpler than wiring up the equivalent Apache Directory Server
beans. The most common alternative configuration requirements are supported by attributes on
the <literal>ldap-server</literal> element and the user is isolated from worrying about which
beans they need create and what the bean property names are. <footnote><para>You can find out
more about the use of the <literal>ldap-server</literal> element in the chapter on <link
xlink:href="#ldap">LDAP</link>.</para></footnote>. Use of a good XML editor while
editing the application context file should provide information on the attributes and elements
that are available. We would recommend that you try out the <link
xlink:href="http://www.springsource.com/products/sts">SpringSource Tool Suite</link> as it
has special features for working with standard Spring namespaces. </para>
<para> To start using the security namespace in your application context, all you need to do is
add the schema declaration to your application context file: <programlisting language="xml">
<![CDATA[
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
...
</beans>
]]></programlisting> In many of the examples you will see (and in the sample) applications, we
will often use "security" as the default namespace rather than "beans", which means we can
omit the prefix on all the security namespace elements, making the content easier to read. You
may also want to do this if you have your application context divided up into separate files
and have most of your security configuration in one of them. Your security application context
file would then start like this <programlisting language="xml"><![CDATA[
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
...
</beans:beans>
]]></programlisting> We'll assume this syntax is being used from now on in this chapter. </para>
<section>
<title>Design of the Namespace</title>
<para> The namespace is designed to capture the most common uses of the framework and provide
a simplified and concise syntax for enabling them within an application. The design is based
around the large-scale dependencies within the framework, and can be divided up into the
following areas: <itemizedlist><listitem><para>
<emphasis>Web/HTTP Security</emphasis> - the most complex part. Sets up the filters
and related service beans used to apply the framework authentication mechanisms, to
secure URLs, render login and error pages and much
more.</para></listitem><listitem><para>
<emphasis>Business Object (Method) Security</emphasis> - options for securing the
service layer.</para></listitem><listitem><para>
<emphasis>AuthenticationManager</emphasis> - handles authentication requests from
other parts of the framework.</para></listitem><listitem><para>
<emphasis>AccessDecisionManager</emphasis> - provides access decisions for web and
method security. A default one will be registered, but you can also choose to use a
custom one, declared using normal Spring bean
syntax.</para></listitem><listitem><para>
<emphasis>AuthenticationProvider</emphasis>s - mechanisms against which the
authentication manager authenticates users. The namespace provides supports for
several standard options and also a means of adding custom beans declared using a
traditional syntax. </para></listitem><listitem><para>
<emphasis>UserDetailsService</emphasis> - closely related to authentication providers,
but often also required by other beans.</para></listitem>
<!-- todo: diagram and link to other sections which describe the interfaces -->
</itemizedlist></para>
<para>We'll see how these work together in the following sections.</para>
</section>
</section>
<section xml:id="ns-getting-started">
<title>Getting Started with Security Namespace Configuration</title>
<para> In this section, we'll look at how you can build up a namespace configuration to use some
of the main features of the framework. Let's assume you initially want to get up and running
as quickly as possible and add authentication support and access control to an existing web
application, with a few test logins. Then we'll look at how to change over to authenticating
against a database or other security information repository. In later sections we'll introduce
more advanced namespace configuration options. </para>
<section xml:id="ns-web-xml">
<title><literal>web.xml</literal> Configuration</title>
<para> The first thing you need to do is add the following filter declaration to your
<literal>web.xml</literal> file: <programlisting language="xml"><![CDATA[
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>]]>
</programlisting> This provides a hook into the Spring Security web
infrastructure. <classname>DelegatingFilterProxy</classname> is a Spring Framework class
which delegates to a filter implementation which is defined as a Spring bean in your
application context. In this case, the bean is named "springSecurityFilterChain", which is
an internal infrastructure bean created by the namespace to handle web security. Note that
you should not use this bean name yourself. Once you've added this to your
<filename>web.xml</filename>, you're ready to start editing your application context file.
Web security services are configured using the <literal>&lt;http&gt;</literal> element.
</para>
</section>
<section xml:id="ns-minimal">
<title>A Minimal <literal>&lt;http&gt;</literal> Configuration</title>
<para> All you need to enable web security to begin with is <programlisting language="xml"><![CDATA[
<http auto-config='true'>
<intercept-url pattern="/**" access="ROLE_USER" />
</http>
]]>
</programlisting> Which says that we want all URLs within our application to be secured,
requiring the role <literal>ROLE_USER</literal> to access them.</para>
<note>
<para>You can use multiple <literal>&lt;intercept-url&gt;</literal> elements to define
different access requirements for different sets of URLs, but they will be evaluated in
the order listed and the first match will be used. So you must put the most specific
matches at the top.</para>
</note>
<para> To add some users, you can define a set of test data directly in the namespace: <programlisting language="xml"><![CDATA[
<authentication-manager>
<authentication-provider>
<user-service>
<user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
<user name="bob" password="bobspassword" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
]]>
</programlisting></para>
<sidebar>
<para>If you are familiar with pre-namespace versions of the framework, you can probably
already guess roughly what's going on here. The &lt;http&gt; element is responsible for
creating a <classname>FilterChainProxy</classname> and the filter beans which it uses.
Common issues like incorrect filter ordering are no longer an issue as the filter
positions are predefined.</para>
<para>The <literal>&lt;authentication-provider&gt;</literal> element creates a
<classname>DaoAuthenticationProvider</classname> bean and the
<literal>&lt;user-service&gt;</literal> element creates an
<classname>InMemoryDaoImpl</classname>. All <literal>authentication-provider</literal>
elements must be within the <literal>authentication-manager</literal> element, which
creates a <classname>ProviderManager</classname> and registers the authentication
providers with it. You can find more detailed information on the beans that are created in
the <link xlink:href="#appendix-namespace">namespace appendix</link>. It's worth
cross-checking this if you want to start understanding what the important classes in the
framework are and how they are used, particularly if you want to customise things
later.</para>
</sidebar>
<para> The configuration above defines two users, their passwords and their roles within the
application (which will be used for access control). It is also possible to load user
information from a standard properties file using the <literal>properties</literal>
attribute on <literal>user-service</literal>. See the section on <link
xlink:href="#core-services-in-memory-service">in-memory authentication</link> for more
details on the file format. Using the <literal>&lt;authentication-provider&gt;</literal>
element means that the user information will be used by the authentication manager to
process authentication requests. You can have multiple
<literal>&lt;authentication-provider&gt;</literal> elements to define different
authentication sources and each will be consulted in turn.</para>
<para> At this point you should be able to start up your application and you will be required
to log in to proceed. Try it out, or try experimenting with the <quote>tutorial</quote>
sample application that comes with the project. The above configuration actually adds quite
a few services to the application because we have used the <literal>auto-config</literal>
attribute. For example, form-based login processing is automatically enabled. </para>
<section xml:id="ns-auto-config">
<title>What does <literal>auto-config</literal> Include?</title>
<para> The <literal>auto-config</literal> attribute, as we have used it above, is just a
shorthand syntax for: <programlisting language="xml"><![CDATA[
<http>
<form-login />
<http-basic />
<logout />
</http>
]]></programlisting> These other elements are responsible for setting up form-login, basic
authentication and logout handling services respectively <footnote><para>In versions prior
to 3.0, this list also included remember-me functionality. This could cause some
confusing errors with some configurations and was removed in 3.0. In 3.0, the addition
of an <classname>AnonymousAuthenticationFilter</classname> is part of the default
<literal>&lt;http></literal> configuration, so the <literal>&lt;anonymous
/></literal> element is added regardless of whether <literal>auto-config</literal>
is enabled.</para></footnote> . They each have attributes which can be used to alter
their behaviour. </para>
</section>
<section xml:id="ns-form-and-basic">
<title>Form and Basic Login Options</title>
<para> You might be wondering where the login form came from when you were prompted to log
in, since we made no mention of any HTML files or JSPs. In fact, since we didn't
explicitly set a URL for the login page, Spring Security generates one automatically,
based on the features that are enabled and using standard values for the URL which
processes the submitted login, the default target URL the user will be sent to after
loggin in and so on. However, the namespace offers plenty of support to allow you to
customize these options. For example, if you want to supply your own login page, you could
use: <programlisting language="xml"><![CDATA[
<http auto-config='true'>
<intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/**" access="ROLE_USER" />
<form-login login-page='/login.jsp'/>
</http>
]]>
</programlisting> Note that you can still use <literal>auto-config</literal>. The
<literal>form-login</literal> element just overrides the default settings. Also note
that we've added an extra <literal>intercept-url</literal> element to say that any
requests for the login page should be available to anonymous users <footnote><para>See the
chapter on <link xlink:href="#anonymous">anonymous authentication</link> for more
details.</para></footnote>. Otherwise the request would be matched by the pattern
<literal>/**</literal> and it wouldn't be possible to access the login page itself! This
is a common configuration error and will result in an infinite loop in the application.
Spring Security will emit a warning in the log if your login page appears to be secured.
It is also possible to have all requests matching a particular pattern bypass the security
filter chain completely: <programlisting language="xml"><![CDATA[
<http auto-config='true'>
<intercept-url pattern="/css/**" filters="none"/>
<intercept-url pattern="/login.jsp*" filters="none"/>
<intercept-url pattern="/**" access="ROLE_USER" />
<form-login login-page='/login.jsp'/>
</http>
]]>
</programlisting> Note that these requests will be completely oblivious to Spring
Security, so you will not be able to access information on the current user or call
secured methods during the request. </para>
<para>If you want to use basic authentication instead of form login, then change the
configuration to <programlisting language="xml"><![CDATA[
<http auto-config='true'>
<intercept-url pattern="/**" access="ROLE_USER" />
<http-basic />
</http>
]]>
</programlisting> Basic authentication will then take precedence and will be used to
prompt for a login when a user attempts to access a protected resource. Form login is
still available in this configuration if you wish to use it, for example through a login
form embedded in another web page. </para>
<section xml:id="ns-form-target">
<title>Setting a Default Post-Login Destination</title>
<para> If a form login isn't prompted by an attempt to access a protected resource, the
<literal>default-target-url</literal> option comes into play. This is the URL the user
will be taken to after logging in, and defaults to "/". You can also configure things so
that they user <emphasis>always</emphasis> ends up at this page (regardless of whether
the login was "on-demand" or they explicitly chose to log in) by setting the
<literal>always-use-default-target</literal> attribute to "true". This is useful if
your application always requires that the user starts at a "home" page, for example: <programlisting language="xml"><![CDATA[
<http>
<intercept-url pattern='/login.htm*' filters='none'/>
<intercept-url pattern='/**' access='ROLE_USER' />
<form-login login-page='/login.htm' default-target-url='/home.htm'
always-use-default-target='true' />
</http>
]]>
</programlisting></para>
</section>
</section>
</section>
<section xml:id="ns-auth-providers">
<title>Using other Authentication Providers</title>
<para> In practice you will need a more scalable source of user information than a few names
added to the application context file. Most likely you will want to store your user
information in something like a database or an LDAP server. LDAP namespace configuration is
dealt with in the <link xlink:href="#ldap">LDAP chapter</link>, so we won't cover it here.
If you have a custom implementation of Spring Security's
<classname>UserDetailsService</classname>, called "myUserDetailsService" in your
application context, then you can authenticate against this using <programlisting language="xml"><![CDATA[
<authentication-manager>
<authentication-provider user-service-ref='myUserDetailsService'/>
</authentication-manager>
]]>
</programlisting> If you want to use a database, then you can use <programlisting language="xml"><![CDATA[
<authentication-manager>
<authentication-provider>
<jdbc-user-service data-source-ref="securityDataSource"/>
</authentication-provider>
</authentication-manager>
]]>
</programlisting> Where "securityDataSource" is the name of a
<classname>DataSource</classname> bean in the application context, pointing at a database
containing the standard Spring Security <link xlink:href="#db_schema_users_authorities">user
data tables</link>. Alternatively, you could configure a Spring Security
<classname>JdbcDaoImpl</classname> bean and point at that using the
<literal>user-service-ref</literal> attribute: <programlisting language="xml"><![CDATA[
<authentication-manager>
<authentication-provider user-service-ref='myUserDetailsService'/>
</authentication-manager>
<beans:bean id="myUserDetailsService"
class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
<beans:property name="dataSource" ref="dataSource"/>
</beans:bean>
]]>
</programlisting> You can also use standard
<interfacename>AuthenticationProvider</interfacename> beans as follows <programlisting language="xml"><![CDATA[
<authentication-manager>
<authentication-provider ref='myAuthenticationProvider'/>
</authentication-manager>
]]>
</programlisting> where <literal>myAuthenticationProvider</literal> is the name of a
bean in your application context which implements
<interfacename>AuthenticationProvider</interfacename>. See <xref linkend="ns-auth-manager"
/> for more on information on how the Spring Security
<interfacename>AuthenticationManager</interfacename> is configured using the namespace. </para>
<section xml:id="ns-password-encoder">
<title>Adding a Password Encoder</title>
<para> Often your password data will be encoded using a hashing algorithm. This is supported
by the <literal>&lt;password-encoder&gt;</literal> element. With SHA encoded passwords,
the original authentication provider configuration would look like this: <programlisting language="xml"><![CDATA[
<authentication-manager>
<authentication-provider>
<password-encoder hash="sha"/>
<user-service>
<user name="jimi" password="d7e6351eaa13189a5a3641bab846c8e8c69ba39f"
authorities="ROLE_USER, ROLE_ADMIN" />
<user name="bob" password="4e7421b1b8765d8f9406d87e7cc6aa784c4ab97f"
authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
]]>
</programlisting></para>
<para> When using hashed passwords, it's also a good idea to use a salt value to protect
against dictionary attacks and Spring Security supports this too. Ideally you would want
to use a randomly generated salt value for each user, but you can use any property of the
<classname>UserDetails</classname> object which is loaded by your
<classname>UserDetailsService</classname>. For example, to use the
<literal>username</literal> property, you would use <programlisting><![CDATA[
<password-encoder hash="sha">
<salt-source user-property="username"/>
</password-encoder>
]]></programlisting> You can use a custom password encoder bean by using the
<literal>ref</literal> attribute of <literal>password-encoder</literal>. This should
contain the name of a bean in the application context which is an instance of Spring
Security's <interfacename>PasswordEncoder</interfacename> interface. </para>
</section>
</section>
</section>
<section xml:id="ns-web-advanced">
<title>Advanced Web Features</title>
<section xml:id="ns-remember-me">
<title>Remember-Me Authentication</title>
<para>See the separate <link xlink:href="#remember-me">Remember-Me chapter</link> for
information on remember-me namespace configuration.</para>
</section>
<section xml:id="ns-requires-channel">
<title>Adding HTTP/HTTPS Channel Security</title>
<para>If your application supports both HTTP and HTTPS, and you require that particular URLs
can only be accessed over HTTPS, then this is directly supported using the
<literal>requires-channel</literal> attribute on <literal>&lt;intercept-url&gt;</literal>: <programlisting language="xml"><![CDATA[
<http>
<intercept-url pattern="/secure/**" access="ROLE_USER" requires-channel="https"/>
<intercept-url pattern="/**" access="ROLE_USER" requires-channel="any"/>
...
</http>]]>
</programlisting> With this configuration in place, if a user attempts to
access anything matching the "/secure/**" pattern using HTTP, they will first be redirected
to an HTTPS URL. The available options are "http", "https" or "any". Using the value "any"
means that either HTTP or HTTPS can be used. </para>
<para> If your application uses non-standard ports for HTTP and/or HTTPS, you can specify a
list of port mappings as follows: <programlisting><![CDATA[
<http>
...
<port-mappings>
<port-mapping http="9080" https="9443"/>
</port-mappings>
</http>]]>
</programlisting>
<!--You can find a more in-depth discussion of channel security
in <xref xlink:href="#channel-security"/-->
</para>
</section>
<section xml:id="ns-session-mgmt">
<title>Session Management</title>
<section>
<title>Detecting Timeouts</title>
<para> You can configure Spring Security to detect the submission of an invalid session ID
and redirect the user to an appropriate URL. This is achieved through the
<literal>session-management</literal> element:<![CDATA[
<http>
...
<session-management invalid-session-url="/sessionTimeout.htm" />
</http>]]></para>
</section>
<section xml:id="ns-concurrent-sessions">
<title>Concurrent Session Control</title>
<para>If you wish to place constraints on a single user's ability to log in to your
application, Spring Security supports this out of the box with the following simple
additions. First you need to add the following listener to your
<filename>web.xml</filename> file to keep Spring Security updated about session
lifecycle events: <![CDATA[
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>
]]> Then add the following lines to your application context: <programlisting language="xml"><![CDATA[
<http>
...
<session-management>
<concurrency-control max-sessions="1" />
</session-management>
</http>]]>
</programlisting> This will prevent a user from logging in multiple times - a
second login will cause the first to be invalidated. Often you would prefer to prevent a
second login, in which case you can use <programlisting language="xml"><![CDATA[
<http>
...
<session-management>
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
</session-management>
</http>]]>
</programlisting> The second login will then be rejected. By
<quote>rejected</quote>, we mean that the user will be sent to the
<literal>authentication-failure-url</literal> if form-based login is being used. If the
second authentication takes place through another non-interactive mechanism, such as
<quote>remember-me</quote>, an <quote>unauthorized</quote> (402) error will be sent to
the client. If instead you want to use an error page, you can add the attribute
<literal>session-authentication-error-url</literal> to the
<literal>session-management</literal> element. </para>
<para> If you are using a customized authentication filter for form-based login, then you
have to configure concurrent session control support explicitly. More details can be found
in the <link xlink:href="#session-mgmt">Session Management chapter</link>. </para>
</section>
</section>
<section xml:id="ns-openid">
<title>OpenID Login</title>
<para>The namespace supports <link xlink:href="http://openid.net/">OpenID</link> login either
instead of, or in addition to normal form-based login, with a simple change: <programlisting language="xml"><![CDATA[
<http>
<intercept-url pattern="/**" access="ROLE_USER" />
<openid-login />
</http>
]]></programlisting> You should then register yourself with an OpenID provider (such as
myopenid.com), and add the user information to your in-memory
<literal>&lt;user-service&gt;</literal>: <programlisting><![CDATA[
<user name="http://jimi.hendrix.myopenid.com/" password="notused"
authorities="ROLE_USER" />
]]></programlisting> You should be able to login using the <literal>myopenid.com</literal> site to
authenticate. </para>
</section>
<section xml:id="ns-custom-filters">
<title>Adding in Your Own Filters</title>
<para>If you've used Spring Security before, you'll know that the framework maintains a chain
of filters in order to apply its services. You may want to add your own filters to the stack
at particular locations or use a Spring Security filter for which there isn't currently a
namespace configuration option (CAS, for example). Or you might want to use a customized
version of a standard namespace filter, such as the
<literal>UsernamePasswordAuthenticationFilter</literal> which is created by the
<literal>&lt;form-login&gt;</literal> element, taking advantage of some of the extra
configuration options which are available by using the bean explicitly. How can you do this
with namespace configuration, since the filter chain is not directly exposed? </para>
<para>The order of the filters is always strictly enforced when using the namespace. When the
application context is being created, the filter beans are sorted by the namespace handling
code and the standard Spring Security filters each have an alias in the namespace and a
well-known position.<note><para>In previous versions, the sorting took place after the
filter instances had been created, during post-processing of the application context. In
version 3.0+ the sorting is now done at the bean metadata level, before the classes have
been instantiated. This has implications for how you add your own filters to the stack
as the entire filter list must be known during the parsing of the
<literal>&lt;http></literal> element, so the syntax has changed slightly in
3.0.</para></note>The filters, aliases and namespace elements/attributes which create
the filters are shown in <xref linkend="filter-stack"/>. The filters are listed in the order
in which they occur in the filter chain. <table xml:id="filter-stack"><title>Standard Filter
Aliases and Ordering</title><tgroup cols="3" align="left"><thead><row><entry
align="center">Alias</entry><entry align="center">Filter Class</entry><entry
align="center">Namespace Element or
Attribute</entry></row></thead><tbody><row><entry>
CHANNEL_FILTER</entry><entry><literal>ChannelProcessingFilter</literal></entry><entry><literal>http/intercept-url@requires-channel</literal></entry></row><row><entry>
CONCURRENT_SESSION_FILTER</entry><entry><literal>ConcurrentSessionFilter</literal>
</entry><entry><literal>session-management/concurrency-control</literal></entry></row><row><entry>
SECURITY_CONTEXT_FILTER</entry><entry><classname>SecurityContextPersistenceFilter</classname></entry><entry><literal>http</literal></entry></row><row><entry>
LOGOUT_FILTER
</entry><entry><literal>LogoutFilter</literal></entry><entry><literal>http/logout</literal></entry></row><row><entry>
X509_FILTER
</entry><entry><literal>X509AuthenticationFilter</literal></entry><entry><literal>http/x509</literal></entry></row><row><entry>
PRE_AUTH_FILTER
</entry><entry><literal>AstractPreAuthenticatedProcessingFilter</literal>
Subclasses</entry><entry>N/A</entry></row><row><entry> CAS_FILTER
</entry><entry><literal>CasAuthenticationFilter</literal></entry><entry>N/A</entry></row><row><entry>
FORM_LOGIN_FILTER
</entry><entry><literal>UsernamePasswordAuthenticationFilter</literal></entry><entry><literal>http/form-login</literal></entry></row><row><entry>
BASIC_AUTH_FILTER
</entry><entry><literal>BasicAuthenticationFilter</literal></entry><entry><literal>http/http-basic</literal></entry></row><row><entry>
SERVLET_API_SUPPORT_FILTER</entry><entry><literal>SecurityContextHolderAwareFilter</literal></entry><entry><literal>http/@servlet-api-provision</literal></entry></row><row><entry>
REMEMBER_ME_FILTER
</entry><entry><classname>RememberMeAuthenticationFilter</classname></entry><entry><literal>http/remember-me</literal></entry></row><row><entry>
ANONYMOUS_FILTER
</entry><entry><literal>AnonymousAuthenticationFilter</literal></entry><entry><literal>http/anonymous</literal></entry></row><row><entry>
SESSION_MANAGEMENT_FILTER</entry><entry><literal>SessionManagementFilter</literal></entry><entry><literal>session-management</literal></entry></row><row><entry>EXCEPTION_TRANSLATION_FILTER
</entry><entry><classname>ExceptionTranslationFilter</classname></entry><entry><literal>http</literal></entry></row><row><entry>
FILTER_SECURITY_INTERCEPTOR
</entry><entry><classname>FilterSecurityInterceptor</classname></entry><entry><literal>http</literal></entry></row><row><entry>
SWITCH_USER_FILTER
</entry><entry><literal>SwitchUserFilter</literal></entry><entry>N/A</entry></row></tbody></tgroup></table>
You can add your own filter to the stack, using the <literal>custom-filter</literal> element
and one of these names to specify the position your filter should appear at: <programlisting language="xml"><![CDATA[
<http>
<custom-filter position="FORM_LOGIN_FILTER" ref="myFilter" />
</http>
<beans:bean id="myFilter" class="com.mycompany.MySpecialAuthenticationFilter"/>
]]>
</programlisting> You can also use the <literal>after</literal> or <literal>before</literal>
attributes if you want your filter to be inserted before or after another filter in the
stack. The names "FIRST" and "LAST" can be used with the <literal>position</literal>
attribute to indicate that you want your filter to appear before or after the entire stack,
respectively. </para>
<tip>
<title>Avoiding filter position conflicts</title>
<para> If you are inserting a custom filter which may occupy the same position as one of the
standard filters created by the namespace then it's important that you don't include the
namespace versions by mistake. Avoid using the <literal>auto-config</literal> attribute
and remove any elements which create filters whose functionality you want to replace. </para>
<para> Note that you can't replace filters which are created by the use of the
<literal>&lt;http&gt;</literal> element itself -
<classname>SecurityContextPersistenceFilter</classname>,
<classname>ExceptionTranslationFilter</classname> or
<classname>FilterSecurityInterceptor</classname>. </para>
</tip>
<para> If you're replacing a namespace filter which requires an authentication entry point
(i.e. where the authentication process is triggered by an attempt by an unauthenticated user
to access to a secured resource), you will need to add a custom entry point bean too. </para>
<section xml:id="ns-entry-point-ref">
<title>Setting a Custom <interfacename>AuthenticationEntryPoint</interfacename></title>
<para> If you aren't using form login, OpenID or basic authentication through the namespace,
you may want to define an authentication filter and entry point using a traditional bean
syntax and link them into the namespace, as we've just seen. The corresponding
<interfacename>AuthenticationEntryPoint</interfacename> can be set using the
<literal>entry-point-ref</literal> attribute on the <literal>&lt;http&gt;</literal>
element. </para>
<para> The CAS sample application is a good example of the use of custom beans with the
namespace, including this syntax. If you aren't familiar with authentication entry points,
they are discussed in the <link xlink:href="#tech-intro-auth-entry-point">technical
overview</link> chapter. </para>
</section>
</section>
<section xml:id="ns-session-fixation">
<title>Session Fixation Attack Protection</title>
<para>
<link xlink:href="http://en.wikipedia.org/wiki/Session_fixation">Session fixation</link>
attacks are a potential risk where it is possible for a malicious attacker to create a
session by accessing a site, then persuade another user to log in with the same session (by
sending them a link containing the session identifier as a parameter, for example). Spring
Security protects against this automatically by creating a new session when a user logs in.
If you don't require this protection, or it conflicts with some other requirement, you can
control the behaviour using the <literal>session-fixation-protection</literal> attribute on
<literal>&lt;http&gt;</literal>, which has three options
<itemizedlist><listitem><para><literal>migrateSession</literal> - creates a new
session and copies the existing session attributes to the new session. This is the
default.</para></listitem><listitem><para><literal>none</literal> - Don't do anything.
The original session will be
retained.</para></listitem><listitem><para><literal>newSession</literal> - Create a
new "clean" session, without copying the existing session
data.</para></listitem></itemizedlist></para>
</section>
</section>
<section xml:id="ns-method-security">
<title>Method Security</title>
<para>From version 2.0 onwards Spring Security has improved support substantially for adding
security to your service layer methods. It provides support for JSR-250 security as well as
the framework's native <literal>@Secured</literal> annotation. You can apply security to a
single bean, using the <literal>intercept-methods</literal> element to decorate the bean
declaration, or you can secure multiple beans across the entire service layer using the
AspectJ style pointcuts. </para>
<section xml:id="ns-global-method">
<title>The <literal>&lt;global-method-security&gt;</literal> Element</title>
<para> This element is used to enable annotation-based security in your application (by
setting the appropriate attributes on the element), and also to group together security
pointcut declarations which will be applied across your entire application context. You
should only declare one <literal>&lt;global-method-security&gt;</literal> element. The
following declaration would enable support for both Spring Security's
<literal>@Secured</literal>, and JSR-250 annotations: <programlisting><![CDATA[
<global-method-security secured-annotations="enabled" jsr250-annotations="enabled"/>
]]>
</programlisting> Adding an annotation to a method (on an class or interface) would then limit
the access to that method accordingly. Spring Security's native annotation support defines a
set of attributes for the method. These will be passed to the
<interfacename>AccessDecisionManager</interfacename> for it to make the actual decision.
This example is taken from the <link xlink:href="#tutorial-sample">tutorial sample</link>,
which is a good starting point if you want to use method security in your application:
<programlisting language="java">
public interface BankService {
@Secured("IS_AUTHENTICATED_ANONYMOUSLY")
public Account readAccount(Long id);
@Secured("IS_AUTHENTICATED_ANONYMOUSLY")
public Account[] findAccounts();
@Secured("ROLE_TELLER")
public Account post(Account account, double amount);
}
</programlisting></para>
<section xml:id="ns-protect-pointcut">
<title>Adding Security Pointcuts using <literal>protect-pointcut</literal></title>
<para> The use of <literal>protect-pointcut</literal> is particularly powerful, as it allows
you to apply security to many beans with only a simple declaration. Consider the following
example: <programlisting language="xml"><![CDATA[
<global-method-security>
<protect-pointcut expression="execution(* com.mycompany.*Service.*(..))"
access="ROLE_USER"/>
</global-method-security>
]]>
</programlisting> This will protect all methods on beans declared in the application
context whose classes are in the <literal>com.mycompany</literal> package and whose class
names end in "Service". Only users with the <literal>ROLE_USER</literal> role will be able
to invoke these methods. As with URL matching, the most specific matches must come first
in the list of pointcuts, as the first matching expression will be used. </para>
</section>
</section>
</section>
<section xml:id="ns-access-manager">
<title>The Default AccessDecisionManager</title>
<para> This section assumes you have some knowledge of the underlying architecture for
access-control within Spring Security. If you don't you can skip it and come back to it later,
as this section is only really relevant for people who need to do some customization in order
to use more than simple role based security. </para>
<para> When you use a namespace configuration, a default instance of
<interfacename>AccessDecisionManager</interfacename> is automatically registered for you and
will be used for making access decisions for method invocations and web URL access, based on
the access attributes you specify in your <literal>intercept-url</literal> and
<literal>protect-pointcut</literal> declarations (and in annotations if you are using
annotation secured methods). </para>
<para> The default strategy is to use an <classname>AffirmativeBased</classname>
<interfacename>AccessDecisionManager</interfacename> with a <classname>RoleVoter</classname>
and an <classname>AuthenticatedVoter</classname>. </para>
<section xml:id="ns-custom-access-mgr">
<title>Customizing the AccessDecisionManager</title>
<para> If you need to use a more complicated access control strategy then it is easy to set an
alternative for both method and web security. </para>
<para> For method security, you do this by setting the
<literal>access-decision-manager-ref</literal> attribute on
<literal>global-method-security</literal>to the Id of the appropriate
<interfacename>AccessDecisionManager</interfacename> bean in the application context: <programlisting language="xml"><![CDATA[
<global-method-security access-decision-manager-ref="myAccessDecisionManagerBean">
...
</global-method-security>
]]></programlisting></para>
<para> The syntax for web security is the same, but on the <literal>http</literal> element: <programlisting><![CDATA[
<http access-decision-manager-ref="myAccessDecisionManagerBean">
...
</http>
]]></programlisting></para>
</section>
</section>
<section xml:id="ns-auth-manager">
<title>The Authentication Manager and the Namespace</title>
<para> The main interface which provides authentication services in Spring Security is the
<interfacename>AuthenticationManager</interfacename>. This is usually an instance of Spring
Security's <classname>ProviderManager</classname> class, which you may already be familiar
with if you've used the framework before. If not, it will be covered later, in <link
xlink:href="#tech-intro-authentication"/>. The bean instance is registered using the
<literal>authentication-manager</literal> namespace element. You can't use a custom
<classname>AuthenticationManager</classname> if you are using either HTTP or method security
through the namespace, but this should not be a problem as you have full control over the
<classname>AuthenticationProvider</classname>s that are used.</para>
<para> You may want to register additional <classname>AuthenticationProvider</classname> beans
with the <classname>ProviderManager</classname> and you can do this using the
<literal>&lt;authentication-provider&gt;</literal> element with the <literal>ref</literal>
attribute, where the value of the attribute is the name of the provider bean you want to add.
For example: <programlisting language="xml"><![CDATA[
<authentication-manager>
<authentication-provider ref="casAuthenticationProvider"/>
</authentication-manager>
<bean id="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<security:custom-authentication-provider />
...
</bean>
]]></programlisting></para>
<para> Another common requirement is that another bean in the context may require a reference to
the <interfacename>AuthenticationManager</interfacename>. There is a special element which
lets you register an alias for the <interfacename>AuthenticationManager</interfacename> and
you can then use this name elsewhere in your application context. <programlisting language="xml"><![CDATA[
<security:authentication-manager alias="authenticationManager">
...
</security:authentication-manager>
<bean id="customizedFormLoginFilter"
class="com.somecompany.security.web.CustomFormLoginFilter">
<property name="authenticationManager" ref="authenticationManager"/>
...
</bean>
]]></programlisting></para>
</section>
</chapter>