SEC-1178: More ref manual updates

This commit is contained in:
Luke Taylor 2009-06-12 23:14:20 +00:00
parent ff5b90ef9d
commit 65d83faef2
11 changed files with 440 additions and 953 deletions

View File

@ -117,10 +117,7 @@
<section xml:id="nsa-access-denied-page">
<title><literal>access-denied-page</literal></title>
<para>
Allows the access denied page to be set (the user will be redirected here if an
<exceptionname>AccessDeniedException</exceptionname> is raised). Corresponds to the
<literal>errorPage</literal> property set on the <classname>AccessDeniedHandlerImpl</classname> which is
used by the <classname>ExceptionTranslationFilter</classname>.
Deprecated in favour of the <literal>access-denied-handler</literal> child element.
</para>
</section>
@ -145,6 +142,16 @@
</para>
</section>
</section>
<section xml:id="nsa-access-denied-handler">
<title><literal>access-denied-handler</literal></title>
<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. See <link xlink:href="#access-denied-handler"/> for more information on the implementation details.
</para>
</section>
<section>
<title>The <literal>&lt;intercept-url&gt;</literal> Element</title>

View File

@ -0,0 +1,170 @@
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="basic">
<info>
<title>Basic and Digest Authentication</title>
</info>
<para>Basic and digest authentiation are alternative authentication mechanisms which are popular
in web applications. Basic authentication is often used with stateless clients which pass
their credentials on each request. It's quite common to use it in combination with form-based
authentication where an application is used through both a browser-based user interface
and as a web-service. However, basic authentication transmits the password as plain text so it
should only really be used over an encrypted transport layer such as HTTPS.</para>
<section xml:id="basic-processing-filter">
<info>
<title><classname>BasicProcessingFilter</classname></title>
</info>
<para><literal>BasicProcessingFilter</literal> is responsible for processing basic
authentication credentials presented in HTTP headers. This can be used for
authenticating calls made by Spring remoting protocols (such as Hessian and Burlap), as
well as normal browser user agents (such as Firefox and Internet Explorer). The standard
governing HTTP Basic Authentication is defined by RFC 1945, Section 11, and
<literal>BasicProcessingFilter</literal> conforms with this RFC. Basic
Authentication is an attractive approach to authentication, because it is very widely
deployed in user agents and implementation is extremely simple (it's just a Base64
encoding of the username:password, specified in an HTTP header).</para>
<section xml:id="basic-config">
<info>
<title>Configuration</title>
</info>
<para>To implement HTTP Basic Authentication, you need to add a
<literal>BasicProcessingFilter</literal> to your filter chain. The application
context should contain <literal>BasicProcessingFilter</literal> and its
required collaborator:</para>
<para>
<programlisting language="xml"><![CDATA[
<bean id="basicProcessingFilter"
class="org.springframework.security.web.authentication.www.BasicProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
</bean>
<bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.www.BasicProcessingFilterEntryPoint">
<property name="realmName" value="Name Of Your Realm"/>
</bean>]]>
</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>BasicProcessingFilterEntryPoint</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
because the HTTP header did not contain a supported authentication request, the filter
chain will continue as normal. The only time the filter chain will be interrupted is if
authentication fails and the <interfacename>AuthenticationEntryPoint</interfacename> is
called.</para>
</section>
</section>
<section xml:id="digest-processing-filter">
<title><classname>DigestProcessingFilter</classname></title>
<para><classname>DigestProcessingFilter</classname> is capable
of processing digest authentication credentials presented in HTTP headers. Digest
Authentication attempts to solve many of the weaknesses of Basic authentication,
specifically by ensuring credentials are never sent in clear text across the wire. Many
user agents support Digest Authentication, including FireFox and Internet Explorer. The
standard governing HTTP Digest Authentication is defined by RFC 2617, which updates an
earlier version of the Digest Authentication standard prescribed by RFC 2069. Most user
agents implement RFC 2617. Spring Security's <classname>DigestProcessingFilter</classname> is
compatible with the "<literal>auth</literal>" quality of protection
(<literal>qop</literal>) prescribed by RFC 2617, which also provides backward
compatibility with RFC 2069. Digest Authentication is a more attractive option if you
need to use unencrypted HTTP (i.e. no TLS/HTTPS) and wish to maximise security of the
authentication process. Indeed Digest Authentication is a mandatory requirement for the
WebDAV protocol, as noted by RFC 2518 Section 17.1.</para>
<para>Digest Authentication is definitely the most secure choice between Form
Authentication, Basic Authentication and Digest Authentication, although extra security
also means more complex user agent implementations. Central to Digest Authentication is
a "nonce". This is a value the server generates. Spring Security's nonce adopts the
following format:</para>
<para>
<programlisting>
base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
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>
<para>The <classname>DigestProcessingFilterEntryPoint</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
(default 300, which equals five minutes). Whist ever the nonce is valid, the digest is
computed by concatenating various strings including the username, password, nonce, URI
being requested, a client-generated nonce (merely a random value which the user agent
generates each request), the realm name etc, then performing an MD5 hash. Both the
server and user agent perform this digest computation, resulting in different hash codes
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>DigestProcessingFilterEntryPoint</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>
<para>An appropriate value for <classname>DigestProcessingFilterEntryPoint</classname>'s
<literal>nonceValiditySeconds</literal> parameter will depend on your application.
Extremely secure applications should note that an intercepted authentication header can
be used to impersonate the principal until the <literal>expirationTime</literal>
contained in the nonce is reached. This is the key principle when selecting an
appropriate setting, but it would be unusual for immensely secure applications to not be
running over TLS/HTTPS in the first instance.</para>
<para>Because of the more complex implementation of Digest Authentication, there are often
user agent issues. For example, Internet Explorer fails to present an
"<literal>opaque</literal>" token on subsequent requests in the same session. Spring
Security filters therefore encapsulate all state information into the
"<literal>nonce</literal>" token instead. In our testing, Spring Security's
implementation works reliably with FireFox and Internet Explorer, correctly handling
nonce timeouts etc.</para>
<section xml:id="digest-config">
<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>DigestProcessingFilter</literal> in
the fitler chain. The application context will need to define the
<literal>DigestProcessingFilter</literal> and its required collaborators:</para>
<para>
<programlisting><![CDATA[
<bean id="digestProcessingFilter" class=
"org.springframework.security.web.authentication.www.DigestProcessingFilter">
<property name="userDetailsService" ref="jdbcDaoImpl"/>
<property name="authenticationEntryPoint" ref="digestProcessingFilterEntryPoint"/>
<property name="userCache" ref="userCache"/>
</bean>
<bean id="digestProcessingFilterEntryPoint" class=
"org.springframework.security.web.authentication.www.DigestProcessingFilterEntryPoint">
<property name="realmName" value="Contacts Realm via Digest Authentication"/>
<property name="key" value="acegi"/>
<property name="nonceValiditySeconds" value="10"/>
</bean>]]>
</programlisting>
</para>
<para>The configured <interfacename>UserDetailsService</interfacename> is needed because
<literal>DigestProcessingFilter</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
<literal>authenticationEntryPoint</literal> property must be
<classname>DigestProcessingFilterEntryPoint</classname>, so that
<classname>DigestProcessingFilter</classname> can obtain the correct
<literal>realmName</literal> and <literal>key</literal> for digest
calculations.</para>
<para>Like <literal>BasicAuthenticationFilter</literal>, if authentication is successful an
<interfacename>Authentication</interfacename> request token will be placed into the
<classname>SecurityContextHolder</classname>. If the authentication event was
successful, or authentication was not attempted because the HTTP header did not contain
a Digest Authentication request, the filter chain will continue as normal. The only time
the filter chain will be interrupted is if authentication fails and the
<interfacename>AuthenticationEntryPoint</interfacename> is called, as discussed in
the previous paragraph.</para>
<para>Digest Authentication's RFC offers a range of additional features to further increase
security. For example, the nonce can be changed on every request. Despite this, Spring
Security implementation was designed to minimise the complexity of the implementation
(and the doubtless user agent incompatibilities that would emerge), and avoid needing to
store server-side state. You are invited to review RFC 2617 if you wish to explore these
features in more detail. As far as we are aware, Spring Security's implementation does
comply with the minimum standards of this RFC.</para>
</section>
</section>
</chapter>

View File

@ -1,60 +0,0 @@
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="basic"><info><title>BASIC Authentication Mechanism</title></info>
<section xml:id="basic-overview"><info><title>Overview</title></info>
<para>Spring Security provides a
<literal>BasicProcessingFilter</literal> which is capable of
processing basic authentication credentials presented in HTTP headers.
This can be used for authenticating calls made by Spring remoting
protocols (such as Hessian and Burlap), as well as normal user agents
(such as Internet Explorer and Navigator). The standard governing HTTP
Basic Authentication is defined by RFC 1945, Section 11, and the
<literal>BasicProcessingFilter</literal> conforms with this RFC. Basic
Authentication is an attractive approach to authentication, because it
is very widely deployed in user agents and implementation is extremely
simple (it's just a Base64 encoding of the username:password,
specified in an HTTP header).</para>
</section>
<section xml:id="basic-config"><info><title>Configuration</title></info>
<para>To implement HTTP Basic Authentication, it is necessary to
define <literal>BasicProcessingFilter</literal> in the filter chain.
The application context will need to define the
<literal>BasicProcessingFilter</literal> and its required
collaborator:</para>
<para><programlisting language="xml"><![CDATA[
<bean id="basicProcessingFilter"
class="org.springframework.security.web.authentication.www.BasicProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
</bean>
<bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.www.BasicProcessingFilterEntryPoint">
<property name="realmName" value="Name Of Your Realm"/>
</bean>]]>
</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
<literal>BasicProcessingFilterEntryPoint</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>.</para>
<para>If the authentication event was successful, or authentication
was not attempted because the HTTP header did not contain a supported
authentication request, the filter chain will continue as normal. The
only time the filter chain will be interrupted is if authentication
fails and the <interfacename>AuthenticationEntryPoint</interfacename> is called,
as discussed in the previous paragraph</para>
</section>
</chapter>

View File

@ -1,347 +0,0 @@
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0"
xml:id="authentication-common-auth-services" xmlns:xlink="http://www.w3.org/1999/xlink">
<info>
<title>Common Authentication Services</title>
</info>
<section xml:id="mechanisms-providers-entry-points">
<info>
<title>Mechanisms, Providers and Entry Points</title>
</info>
<para>To use Spring Security's authentication services, you'll usually need to configure a web
filter, together with an <classname>AuthenticationProvider</classname> and
<interfacename>AuthenticationEntryPoint</interfacename>. In this section we are going to
explore an example application that needs to support both form-based authentication (so a nice
HTML page is presented to a user for them to login) and BASIC authentication (so a web service
or similar can access protected resources).</para>
<para>The <literal>filter-chain-map</literal> syntax from the security namespace allows you to
define the mapping from URLs to filter chains, using a sequence of
<literal>filter-chain</literal> child elements. Each of these defines a set of URLs using
the <literal>pattern</literal> attribute and a chain of filters using the
<literal>filters</literal> attribute.What's important to note at this stage is that a series
of filters will be run - in the order specified by the declaration - and each of those filters
are actually the <literal>id</literal> of another bean in the application context. So, in our
case some extra beans will also appear in the application context, and they'll be named
<literal>httpSessionContextIntegrationFilter</literal>, <literal>logoutFilter</literal> and
so on. The order that the filters should appear is discussed in the filters section of the
reference guide - although they are correct in the above example.</para>
<para>In our example we have the
<literal>UsernamePasswordAuthenticationProcessingFilter</literal> and
<literal>BasicProcessingFilter</literal> being used. These are the "authentication
mechanisms" that respond to form-based authentication and BASIC HTTP header-based
authentication respectively (we discussed the role of authentication mechanisms earlier in
this reference guide). If you weren't using form or BASIC authentication, neither of these
beans would be defined. You'd instead define filters applicable to your desired authentication
environment, such as <literal>DigestProcessingFilter</literal> or
<literal>CasProcessingFilter</literal>. Refer to the individual chapters of this part of the
reference guide to learn how to configure each of these authentication mechanisms.</para>
<para>Recall that <classname>HttpSessionContextIntegrationFilter</classname> keeps the contents
of the <interfacename>SecurityContext</interfacename> between invocations inside an HTTP
session. This means the authentication mechanisms are only used once, being when the principal
initially tries to authenticate. The rest of the time the authentication mechanisms sit there
and silently pass the request through to the next filter in the chain. That is a practical
requirement due to the fact that few authentication approaches present credentials on each and
every call (BASIC authentication being a notable exception), but what happens if a principal's
account gets cancelled or disabled or otherwise changed (eg an increase or decrease in
<literal>GrantedAuthority[]</literal>s) after the initial authentication step? Let's look at
how that is handled now.</para>
<para>The major authorization provider for secure objects has previously been introduced as
<classname>AbstractSecurityInterceptor</classname>. This class needs to have access to an
<interfacename>AuthenticationManager</interfacename>. It also has configurable settings to
indicate whether an <interfacename>Authentication</interfacename> object should be
re-authenticated on each secure object invocation. By default it just accepts any
<interfacename>Authentication</interfacename> inside the
<classname>SecurityContextHolder</classname> is authenticated if
<literal>Authentication.isAuthenticated()</literal> returns true. This is great for
performance, but not ideal if you want to ensure up-to-the-moment authentication validity. For
such cases you'll probably want to set the
<literal>AbstractSecurityInterceptor.alwaysReauthenticate</literal> property to true.</para>
<para>You might be asking yourself, "what's this
<interfacename>AuthenticationManager</interfacename>?". We haven't explored it before, but
we have discussed the concept of an <classname>AuthenticationProvider</classname>. Quite
simply, an <interfacename>AuthenticationManager</interfacename> is responsible for passing
requests through a chain of AuthenticationProviders. It's a little like the filter chain we
discussed earlier, although there are some differences. There is only one
<interfacename>AuthenticationManager</interfacename> implementation shipped with Spring
Security, so let's look at how it's configured for the example we're using in this
chapter:</para>
<para>
<programlisting><![CDATA[
<bean id="authenticationManager"
class="org.springframework.security.authentication.ProviderManager">
<property name="providers">
<list>
<ref local="daoAuthenticationProvider"/>
<ref local="anonymousAuthenticationProvider"/>
<ref local="rememberMeAuthenticationProvider"/>
</list>
</property>
</bean>]]></programlisting>
</para>
<para>It's probably worth mentioning at this point that your authentication mechanisms (which
are usually filters) are also injected with a reference to the
<interfacename>AuthenticationManager</interfacename>. So both
<classname>AbstractSecurityInterceptor</classname> as well as the authentication mechanisms
will use the above <literal>ProviderManager</literal> to poll a list of
<classname>AuthenticationProvider</classname>s.</para>
<para>In our example we have three providers. They are tried in the order shown (which is
implied by the use of a <literal>List</literal> instead of a <literal>Set</literal>), with
each provider able to attempt authentication, or skip authentication by simply returning
<literal>null</literal>. If all implementations return null, the
<literal>ProviderManager</literal> will throw a suitable exception. If you're interested in
learning more about chaining providers, please refer to the <literal>ProviderManager</literal>
JavaDocs.</para>
<para>The providers to use will sometimes be interchangeable with the authentication mechanisms,
whilst at other times they will depend on a specific authentication mechanism. For example,
the <literal>DaoAuthenticationProvider</literal> just needs a string-based username and
password. Various authentication mechanisms result in the collection of a string-based
username and password, including (but not limited to) BASIC and form authentication. Equally,
some authentication mechanisms create an authentication request object which can only be
interpreted by a single type of <classname>AuthenticationProvider</classname>. An example of
this one-to-one mapping would be JA-SIG CAS, which uses the notion of a service ticket which
can therefore only be authenticated by <literal>CasAuthenticationProvider</literal>. A further
example of a one-to-one mapping would be the LDAP authentication mechanism, which can only be
processed an the <literal>LdapAuthenticationProvider</literal>. The specifics of such
relationships are detailed in the JavaDocs for each class, plus the authentication
approach-specific chapters of this reference guide. You need not be terribly concerned about
this implementation detail, because if you forget to register a suitable provider, you'll
simply receive a <literal>ProviderNotFoundException</literal> when an attempt to authenticate
is made.</para>
<para>After configuring the correct authentication mechanisms in the
<classname>FilterChainProxy</classname>, and ensuring that a corresponding
<classname>AuthenticationProvider</classname> is registered in the
<literal>ProviderManager</literal>, your last step is to configure an
<interfacename>AuthenticationEntryPoint</interfacename>. Recall that earlier we discussed
the role of <classname>ExceptionTranslationFilter</classname>, which is used when HTTP-based
requests should receive back an HTTP header or HTTP redirect in order to start authentication.
Continuing on with our earlier example:</para>
<para>
<programlisting><![CDATA[
<bean id="exceptionTranslationFilter"
class="org.springframework.security.web.access.ExceptionTranslationFilter">
<property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
<property name="accessDeniedHandler">
<bean class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<property name="errorPage" value="/accessDenied.jsp"/>
</bean>
</property>
</bean>
<bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/login.jsp"/>
<property name="forceHttps" value="false"/>
</bean>]]></programlisting>
</para>
<para>Notice that the <classname>ExceptionTranslationFilter</classname> requires two
collaborators. The first, <literal>AccessDeniedHandlerImpl</literal>, uses a
<literal>RequestDispatcher</literal> forward to display the specified access denied error
page. We use a forward so that the <classname>SecurityContextHolder</classname> still contains
details of the principal, which may be useful for display 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). <literal>AccessDeniedHandlerImpl</literal> will
also set the HTTP header to 403, which is the official error code to indicate access denied.
In the case of the <literal>AuthentionEntryPoint</literal>, here we're setting what action we
would like taken when an unauthenticated principal attempts to perform a protected operation.
Because in our example we're going to be using form-based authentication, we specify
<literal>AuthenticationProcessinFilterEntryPoint</literal> and the URL of the login page.
Your application will usually only have one entry point, and most authentication approaches
define their own specific <interfacename>AuthenticationEntryPoint</interfacename>. Details of
which entry point to use for each authentication approach is discussed in the authentication
approach-specific chapters of this reference guide.</para>
</section>
<section xml:id="userdetails-and-associated-types">
<info>
<title>UserDetails and Associated Types</title>
</info>
<para>As mentioned in the first part of the reference guide, most authentication providers take
advantage of the <interfacename>UserDetails</interfacename> and
<interfacename>UserDetailsService</interfacename> interfaces. The contract for this latter
interface consists of a single method:</para>
<para>
<programlisting>
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException;
</programlisting>
</para>
<para>The returned <interfacename>UserDetails</interfacename> is an interface that provides
getters that guarantee non-null provision of basic authentication information such as the
username, password, granted authorities and whether the user 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.
Generally such providers will be using the returned <interfacename>UserDetails</interfacename>
object just for its <literal>GrantedAuthority[]</literal> information, because some other
system (like LDAP or X509 or CAS etc) has undertaken the responsibility of actually validating
the credentials.</para>
<para>A single concrete implementation of <interfacename>UserDetails</interfacename> is provided
with Spring Security, being the <literal>User</literal> class. Spring Security users will need
to decide when writing their <interfacename>UserDetailsService</interfacename> what concrete
<interfacename>UserDetails</interfacename> class to return. In most cases
<literal>User</literal> will be used directly or subclassed, although special circumstances
(such as object relational mappers) may require users to write their own
<interfacename>UserDetails</interfacename> implementation from scratch. This is not such an
unusual situation, and users should not hesitate to simply return their normal domain object
that represents a user of the system. This is especially common given that
<interfacename>UserDetails</interfacename> is often used to store additional
principal-related properties (such as their telephone number and email address), so that they
can be easily used by web views.</para>
<para>Given <interfacename>UserDetailsService</interfacename> is so simple to implement, it
should be easy for users to retrieve authentication information using a persistence strategy
of their choice. Having said that, Spring Security does include a couple of useful base
implementations, which we'll look at below.</para>
<section xml:id="in-memory-service">
<info>
<title>In-Memory Authentication</title>
</info>
<para>Whilst it is easy to use create a custom
<interfacename>UserDetailsService</interfacename> implementation that extracts information
from a persistence engine of choice, many applications do not require such complexity. This
is particularly true if you're undertaking a rapid prototype 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 from the
security <link xlink:href="#namespace-minimal">namespace</link>: <programlisting><![CDATA[
<user-service id="userDetailsService">
<user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
<user name="bob" password="bobspassword" authorities="ROLE_USER" />
</user-service>
]]>
</programlisting> This also suppots the use of an external properties file: <programlisting><![CDATA[
<user-service id="userDetailsService" properties="users.properties"/>
]]></programlisting> The properties file should contain entries in the form
<programlisting>
username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]
</programlisting>
For example
<programlisting>
jimi=jimispassword,ROLE_USER,ROLE_ADMIN,enabled
bob=bobspassword,ROLE_USER,enabled
</programlisting></para>
</section>
<section xml:id="jdbc-service">
<info>
<title>JDBC Authentication</title>
</info>
<para>Spring Security also includes a <interfacename>UserDetailsService</interfacename> that
can obtain authentication information from a JDBC data source. Internally 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>
<![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"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="userDetailsService" class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
<property name="dataSource" ref="dataSource"/>
</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 per normal Spring options. </para>
<section xml:id="jdbc-default-schema">
<title>Default User Database Schema</title>
<para> Irrespective of the database you are using and how a <literal>DataSource</literal> is
obtained, a standard schema must be in place. The DDL for an HSQL database instance would
be:
<programlisting>
CREATE TABLE users (
username VARCHAR(50) NOT NULL PRIMARY KEY,
password VARCHAR(50) NOT NULL,
enabled BIT NOT NULL
);
CREATE TABLE authorities (
username VARCHAR(50) NOT NULL,
authority VARCHAR(50) NOT NULL
);
ALTER TABLE authorities ADD CONSTRAINT fk_authorities_users \
foreign key (username) REFERENCES users(username);
</programlisting></para>
<para>If the default schema is unsuitable for your needs, <literal>JdbcDaoImpl</literal>
provides properties that allow customisation of the SQL statements. Please refer to the
JavaDocs for details, but note that the class is not intended for complex custom
subclasses. If you have a complex schema or would like a custom
<interfacename>UserDetails</interfacename> implementation returned, you'd be better off
writing your own <interfacename>UserDetailsService</interfacename>. The base
implementation provided with Spring Security is intended for typical situations, rather
than catering for all possible requirements.</para>
</section>
</section>
</section>
<section xml:id="concurrent-sessions">
<info>
<title>Concurrent Session Handling</title>
</info>
<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 "Batman" from logging onto
the web application from two different sessions.</para>
<para>To use concurrent session support, you'll need to add the following to
<literal>web.xml</literal>: <programlisting><![CDATA[
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener> ]]>
</programlisting></para>
<para>In addition, you will need to add the
<literal>org.springframework.security.web.authentication.concurrent.ConcurrentSessionFilter</literal>
to your <classname>FilterChainProxy</classname>. The
<classname>ConcurrentSessionFilter</classname> requires two properties,
<literal>sessionRegistry</literal>, which generally points to an instance of
<literal>SessionRegistryImpl</literal>, and <literal>expiredUrl</literal>, which points to
the page to display when a session has expired.</para>
<para>The <literal>web.xml</literal>
<literal>HttpSessionEventPublisher</literal> 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.</para>
<para>You will also need to wire up the <classname>ConcurrentSessionControllerImpl</classname>
and refer to it from your <literal>ProviderManager</literal> bean:</para>
<para>
<programlisting><![CDATA[
<bean id="authenticationManager"
class="org.springframework.security.authentication.ProviderManager">
<property name="providers">
<!-- your providers go here -->
</property>
<property name="sessionController" ref="concurrentSessionController"/>
</bean>
<bean id="concurrentSessionController" class=
"org.springframework.security.authentication.concurrent.ConcurrentSessionControllerImpl">
<property name="maximumSessions" value="1"/>
<property name="sessionRegistry">
<bean
class="org.springframework.security.authentication.concurrent.SessionRegistryImpl"/>
<property>
</bean>
]]></programlisting>
</para>
</section>
<section xml:id="authentication-taglibs">
<info>
<title>Authentication Tag Libraries</title>
</info>
<para><literal>AuthenticationTag</literal> is used to simply output a property of the current
<interfacename>Authentication</interfacename> object to the web page.</para>
<para>The following JSP fragment illustrates how to use the
<literal>AuthenticationTag</literal>:</para>
<para>
<programlisting>&lt;security:authentication property="principal.username"/&gt;</programlisting>
</para>
<para>This tag would cause the principal's name to be output. Here we are assuming the
<literal>Authentication.getPrincipal()</literal> is a
<interfacename>UserDetails</interfacename> object, which is generally the case when using
one of Spring Security's stadard <classname>AuthenticationProvider</classname>
implementations.</para>
</section>
</chapter>

View File

@ -1,144 +0,0 @@
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="digest"><info><title>Digest Authentication</title></info>
<section xml:id="digest-overview"><info><title>Overview</title></info>
<para>Spring Security provides a
<literal>DigestProcessingFilter</literal> which is capable of
processing digest authentication credentials presented in HTTP
headers. Digest Authentication attempts to solve many of the
weaknesses of Basic authentication, specifically by ensuring
credentials are never sent in clear text across the wire. Many user
agents support Digest Authentication, including FireFox and Internet
Explorer. The standard governing HTTP Digest Authentication is defined
by RFC 2617, which updates an earlier version of the Digest
Authentication standard prescribed by RFC 2069. Most user agents
implement RFC 2617. Spring Security
<literal>DigestProcessingFilter</literal> is compatible with the
"<literal>auth</literal>" quality of protection
(<literal>qop</literal>) prescribed by RFC 2617, which also provides
backward compatibility with RFC 2069. Digest Authentication is a
highly attractive option if you need to use unencrypted HTTP (ie no
TLS/HTTPS) and wish to maximise security of the authentication
process. Indeed Digest Authentication is a mandatory requirement for
the WebDAV protocol, as noted by RFC 2518 Section 17.1, so we should
expect to see it increasingly deployed and replacing Basic
Authentication.</para>
<para>Digest Authentication is definitely the most secure choice
between Form Authentication, Basic Authentication and Digest
Authentication, although extra security also means more complex user
agent implementations. Central to Digest Authentication is a "nonce".
This is a value the server generates. Spring Security's nonce adopts
the following format:</para>
<para><programlisting>
base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
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>
<para>The <literal>DigestProcessingFilterEntryPoint</literal> 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 (default 300, which
equals five minutes). Whist ever the nonce is valid, the digest is
computed by concatenating various strings including the username,
password, nonce, URI being requested, a client-generated nonce (merely
a random value which the user agent generates each request), the realm
name etc, then performing an MD5 hash. Both the server and user agent
perform this digest computation, resulting in different hash codes 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
<literal>DigestProcessingFilterEntryPoint</literal> 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>
<para>An appropriate value for
<literal>DigestProcessingFilterEntryPoint</literal>'s
<literal>nonceValiditySeconds</literal> parameter will depend on your
application. Extremely secure applications should note that an
intercepted authentication header can be used to impersonate the
principal until the <literal>expirationTime</literal> contained in the
nonce is reached. This is the key principle when selecting an
appropriate setting, but it would be unusual for immensely secure
applications to not be running over TLS/HTTPS in the first
instance.</para>
<para>Because of the more complex implementation of Digest
Authentication, there are often user agent issues. For example,
Internet Explorer fails to present an "<literal>opaque</literal>"
token on subsequent requests in the same session. Spring Security
filters therefore encapsulate all state information into the
"<literal>nonce</literal>" token instead. In our testing, Spring
Security implementation works reliably with FireFox and Internet
Explorer, correctly handling nonce timeouts etc.</para>
</section>
<section xml:id="digest-config"><info><title>Configuration</title></info>
<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>DigestProcessingFilter</literal> in the fitler chain. The
application context will need to define the
<literal>DigestProcessingFilter</literal> and its required
collaborators:</para>
<para><programlisting>
<![CDATA[
<bean id="digestProcessingFilter" class=
"org.springframework.security.web.authentication.www.DigestProcessingFilter">
<property name="userDetailsService" ref="jdbcDaoImpl"/>
<property name="authenticationEntryPoint" ref="digestProcessingFilterEntryPoint"/>
<property name="userCache" ref="userCache"/>
</bean>
<bean id="digestProcessingFilterEntryPoint" class=
"org.springframework.security.web.authentication.www.DigestProcessingFilterEntryPoint">
<property name="realmName" value="Contacts Realm via Digest Authentication"/>
<property name="key" value="acegi"/>
<property name="nonceValiditySeconds" value="10"/>
</bean>]]>
</programlisting></para>
<para>The configured <interfacename>UserDetailsService</interfacename> is needed
because <literal>DigestProcessingFilter</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
<literal>DaoAuthenticationProvider</literal>. The
<literal>authenticationEntryPoint</literal> property must be
<literal>DigestProcessingFilterEntryPoint</literal>, so that
<literal>DigestProcessingFilter</literal> can obtain the correct
<literal>realmName</literal> and <literal>key</literal> for digest
calculations.</para>
<para>Like <literal>BasicAuthenticationFilter</literal>, if
authentication is successful an <interfacename>Authentication</interfacename>
request token will be placed into the
<classname>SecurityContextHolder</classname>. If the authentication event
was successful, or authentication was not attempted because the HTTP
header did not contain a Digest Authentication request, the filter
chain will continue as normal. The only time the filter chain will be
interrupted is if authentication fails and the
<interfacename>AuthenticationEntryPoint</interfacename> is called, as discussed in
the previous paragraph.</para>
<para>Digest Authentication's RFC offers a range of additional
features to further increase security. For example, the nonce can be
changed on every request. Despite this, Spring Security implementation
was designed to minimise the complexity of the implementation (and the
doubtless user agent incompatibilities that would emerge), and avoid
needing to store server-side state. You are invited to review RFC 2617
if you wish to explore these features in more detail. As far as we are
aware, Spring Security's implementation does comply with the minimum
standards of this RFC.</para>
</section>
</chapter>

View File

@ -63,7 +63,5 @@
</note>
If authentication fails, the configured <interfacename>AuthenticationFailureHandler</interfacename> will be invoked.
</para>
</section>
</chapter>

View File

@ -145,121 +145,4 @@ public void afterPropertiesSet() throws Exception {
whatever means you think fit (eg <literal>new Person();</literal>) and they will have the
security interceptor applied.</para>
</section>
<section xml:id="filter-invocation-authorization">
<info>
<title>FilterInvocation Security Interceptor</title>
</info>
<para>To secure <classname>FilterInvocation</classname>s, developers need to add a
<classname>FilterSecurityInterceptor</classname> to their filter chain. A typical
configuration example is provided below:</para>
<para>In the application context you will need to configure three beans:</para>
<programlisting>
<![CDATA[
<bean id="exceptionTranslationFilter"
class="org.springframework.security.web.access.ExceptionTranslationFilter">
<property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
</bean>
<bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/acegilogin.jsp"/>
<property name="forceHttps" value="false"/>
</bean>
<bean id="filterSecurityInterceptor"
class="org.springframework.security.intercept.web.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
<property name="securityMetadataSource">
<security:filter-security-metadata-source>
<security:intercept-url pattern="/secure/super/**" access="ROLE_WE_DONT_HAVE"/>
<security:intercept-url pattern="/secure/**" access="ROLE_SUPERVISOR,ROLE_TELLER"/>
</security:filter-security-metadata-source>
</property>
</bean>]]> </programlisting>
<para>The <classname>ExceptionTranslationFilter</classname> provides the bridge between Java
exceptions and HTTP responses. It is solely concerned with maintaining the user interface.
This filter does not do any actual security enforcement. If an
<exceptionname>AuthenticationException</exceptionname> is detected, the filter will call the
AuthenticationEntryPoint to commence the authentication process (e.g. a user login).</para>
<para>The <interfacename>AuthenticationEntryPoint</interfacename> will be called if the user
requests a secure HTTP resource but they are not authenticated. The class handles presenting
the appropriate response to the user so that authentication can begin. Three concrete
implementations are provided with Spring Security:
<classname>LoginUrlAuthenticationEntryPoint</classname> for commencing a form-based
authentication, <literal>BasicProcessingFilterEntryPoint</literal> for commencing a HTTP Basic
authentication process, and <literal>CasProcessingFilterEntryPoint</literal> for commencing a
JA-SIG Central Authentication Service (CAS) login. The
<classname>LoginUrlAuthenticationEntryPoint</classname> and
<literal>CasProcessingFilterEntryPoint</literal> have optional properties related to forcing
the use of HTTPS, so please refer to the JavaDocs if you require this.</para>
<para><classname>FilterSecurityInterceptor</classname> is responsible for handling the security
of HTTP resources. Like any other security interceptor, it requires a reference to an
<interfacename>AuthenticationManager</interfacename> and an
<interfacename>AccessDecisionManager</interfacename>, which are both discussed in separate
sections below. The <classname>FilterSecurityInterceptor</classname> is also configured with
configuration attributes that apply to different HTTP URL requests. A full discussion of
configuration attributes is provided in the High Level Design section of this document.</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. The second is by writing your own
<interfacename>SecurityMetadataSource</interfacename>, although 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>FilterInvocationDefinitionSource</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>FilterInvocationDefinitionSource</interfacename> as an
<interfacename>SecurityMetadataSource</interfacename>, as the distinction is of little
relevance to most users of the <classname>FilterSecurityInterceptor</classname>.</para>
<para>When using the namespace option to configure the interceptor, commas are used to delimit
the different configuration attributes that apply to each HTTP URL. Each configuration
attribute is assigned into its own <literal>SecurityConfig</literal> object. The
<literal>SecurityConfig</literal> object is discussed in the High Level Design section. The
<interfacename>SecurityMetadataSource</interfacename> created by the property editor,
<interfacename>FilterInvocationDefinitionSource</interfacename>, matches configuration
attributes against <literal>FilterInvocations</literal> based on expression evaluation of the
request URL. Two standard expression syntaxes are supported. The default is to treat all
expressions as Apache Ant paths and regular expressions are also supported for ore complex
cases. The <literal>path-type</literal> attribute is used to specify the type of pattern being
used. It is not possible to mix expression syntaxes within the same definition. For example,
the previous configuration using regular expressions instead of Ant paths would be written as
follows:</para>
<programlisting><![CDATA[
<bean id="filterInvocationInterceptor"
class="org.springframework.security.intercept.web.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
<property name="runAsManager" ref="runAsManager"/>
<property name="securityMetadataSource">
<security:filter-security-metadata-source path-type="regex">
<security:intercept-url pattern="\A/secure/super/.*\Z" access="ROLE_WE_DONT_HAVE"/>
<security:intercept-url pattern="\A/secure/.*\" access="ROLE_SUPERVISOR,ROLE_TELLER"/>
</security:filter-security-metadata-source>
</property>
</bean>]]> </programlisting>
<para>Irrespective of the type of expression syntax used, expressions are always evaluated in
the order they are defined. Thus it is important that more specific expressions are defined
higher in the list than less specific expressions. This is reflected in our example above,
where the more specific <literal>/secure/super/</literal> pattern appears higher than the less
specific <literal>/secure/</literal> pattern. If they were reversed, the
<literal>/secure/</literal> pattern would always match and the
<literal>/secure/super/</literal> pattern would never be evaluated.</para>
<para>As with other security interceptors, the <literal>validateConfigAttributes</literal>
property is observed. When set to <literal>true</literal> (the default), at startup time the
<classname>FilterSecurityInterceptor</classname> will evaluate if the provided configuration
attributes are valid. It does this by checking each configuration attribute can be processed
by either the <interfacename>AccessDecisionManager</interfacename> or the
<literal>RunAsManager</literal>. If neither of these can process a given configuration
attribute, an exception is thrown.</para>
</section>
</chapter>

View File

@ -0,0 +1,226 @@
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="security-filter-chain"
xmlns:xlink="http://www.w3.org/1999/xlink">
<info>
<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
<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>
<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[
<filter>
<filter-name>myFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<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
<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[
<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
<sec:filter-chain-map path-type="ant">
<sec:filter-chain pattern="/webServices/**" filters="
securityContextPersistenceFilterWithASCFalse,
basicProcessingFilter,
exceptionTranslationFilter,
filterSecurityInterceptor" />
<sec:filter-chain pattern="/**" filters="
securityContextPersistenceFilterWithASCTrue,
authenticationProcessingFilter,
exceptionTranslationFilter,
filterSecurityInterceptor" />
</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>
<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>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="#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>
<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>
</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 -
<classname>UsernamePasswordAuthenticationProcessingFilter</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>
</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>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>
</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>
</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>
</section>
<!--
<section xml:id="taglib">
<info>
<title>Tag Libraries</title>
</info>
<para>Spring Security comes bundled with several JSP tag libraries which provide a range of
different services.</para>
<section xml:id="taglib-config">
<info>
<title>Configuration</title>
</info>
<para>All taglib classes are included in the core
<literal>spring-security-taglibs-&lt;version>.jar</literal> file, with the
<literal>security.tld</literal> located in the JAR's <literal>META-INF</literal>
directory. This means for JSP 1.2+ web containers you can simply include the JAR in the
WAR's <literal>WEB-INF/lib</literal> directory and it will be available.</para>
</section>
<section xml:id="taglib-usage">
<info>
<title>Usage</title>
</info>
<para>Now that you've configured the tag libraries, refer to the individual reference guide
sections for details on how to use them. Note that when using the tags, you should include
the taglib reference in your JSP:
<programlisting>
&lt;%@ taglib prefix='security' uri='http://www.springframework.org/security/tags' %&gt;
</programlisting></para>
</section>
</section>-->
</chapter>

View File

@ -97,7 +97,24 @@
Security.</para>
</partintro>
<xi:include href="technical-overview.xml"/>
<xi:include href="web-infrastructure.xml"/>
<xi:include href="core-services.xml"/>
</part>
<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>
</partintro>
<xi:include href="security-filter-chain.xml"/>
<xi:include href="core-filters.xml"/>
<xi:include href="basic-and-digest-auth.xml"/>
<xi:include href="remember-me-authentication.xml"/>
<xi:include href="concurrent-sessions.xml"/>
</part>
<part xml:id="authentication">
<title>Authentication</title>
@ -120,12 +137,7 @@
the project web site.</para>
</footnote>. </para>
</partintro>
<xi:include href="common-auth-services.xml"/>
<xi:include href="dao-auth-provider.xml"/>
<xi:include href="form-authentication.xml"/>
<xi:include href="basic-authentication.xml"/>
<xi:include href="digest-authentication.xml"/>
<xi:include href="anon-auth-provider.xml"/>
<xi:include href="runas-auth-provider.xml"/>
</part>
@ -145,24 +157,21 @@
</partintro>
<xi:include href="authorization-common.xml"/>
<xi:include href="secured-objects.xml"/>
<xi:include href="domain-acls.xml"/>
</part>
<part xml:id="advanced-topics">
<title>Advanced Topics</title>
<!--
Essentially standalone features which do not have to follow on directly from earlier chapters
-->
<partintro>
<para>
In this part we cover some of the more advanced features of the framework.
</para>
<partintro>
<para> In this part we cover some of the more advanced features of the framework. </para>
</partintro>
<xi:include href="remember-me-authentication.xml"/>
<xi:include href="domain-acls.xml"/>
<xi:include href="preauth.xml"/>
<xi:include href="ldap-auth-provider.xml"/>
<xi:include href="ldap-auth-provider.xml"/>
<xi:include href="jaas-auth-provider.xml"/>
<xi:include href="cas-auth-provider.xml"/>
<xi:include href="x509-auth-provider.xml"/>
<xi:include href="cas-auth-provider.xml"/>
<xi:include href="x509-auth-provider.xml"/>
</part>
<xi:include href="appendix-db-schema.xml"/>
<xi:include href="appendix-namespace.xml"/>

View File

@ -108,8 +108,8 @@ if (principal instanceof UserDetails) {
required.</para>
<para> On successful authentication, <interfacename>UserDetails</interfacename> is used to
build the <interfacename>Authentication</interfacename> object that is stored in the
<classname>SecurityContextHolder</classname> (more on this in <link
xlink:href="#tech-intro-authentication-mgr"/> below). The good news is that we provide a
<classname>SecurityContextHolder</classname> (more on this <link
xlink:href="#tech-intro-authentication-mgr">below</link>). The good news is that we provide a
number of <interfacename>UserDetailsService</interfacename> implementations, including one
that uses an in-memory map (<classname>InMemoryDaoImpl</classname>) and another that uses
JDBC (<interfacename>JdbcDaoImpl</interfacename>). Most users tend to write their own,
@ -321,33 +321,14 @@ Successfully authenticated. Security context contains: \
(or equivalent) that reads the third-party user information from a location, build a
Spring Security-specific <interfacename>Authentication</interfacename> object, and put it
onto the <classname>SecurityContextHolder</classname>.</para>
<para>
If you're wondering how the <interfacename>AuthenticationManager</interfacename>
manager is implemented in a real world example, we'll look at that in
</para>
</section>
</section>
<section xml:id="tech-intro-authentication-mgr">
<title>The <interfacename>AuthenticationManager</interfacename></title>
<para>The <interfacename>AuthenticationManager</interfacename> is just an interface, so the
implementation can be anything we choose, but how does it work in practice. What if we need
to check multiple authentication databases? 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
<interfacename>UserDetailsService</interfacename>? If not, head back to the previous
section and refresh your memory. The most common approach to verifying an authentication
request is to load the corresponding <interfacename>UserDetails</interfacename> and check
the loaded password against the one that has been entered by the user. This is the approach
used by the <classname>DaoAuthenticationProvider</classname>, which is most commonly used to
wrap a <interfacename>UserDetailsService</interfacename> to implement an
<interfacename>AuthenticationProvider</interfacename>. 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>
</section>
</section>
<section>
<section xml:id="tech-intro-web-authentication">
<title>Authentication in a Web Application</title>
<para> Now let's explore the situation where you are using Spring Security in a web application
(without <filename>web.xml</filename> security enabled). How is a user authenticated and the
@ -410,7 +391,7 @@ Successfully authenticated. Security context contains: \
<interfacename>AuthenticationEntryPoint</interfacename> (if the principal has not been
authenticated and therefore we need to go commence step three).</para>
</section>
<section xml:id="tech-auth-entry-point">
<section xml:id="tech-intro-auth-entry-point">
<title>AuthenticationEntryPoint</title>
<para>The <interfacename>AuthenticationEntryPoint</interfacename> is responsible for step
three in the above list. As you can imagine, each web application will have a default
@ -438,7 +419,7 @@ Successfully authenticated. Security context contains: \
rejected the request, the authentication mechanism will ask the user agent to retry (step
two above).</para>
</section>
<section xml:id="tech-sec-context-persistence">
<section xml:id="tech-intro-sec-context-persistence">
<title>Storing the <interfacename>SecurityContext</interfacename> between requests</title>
<para>Depending on the type of application, there may need to be a strategy in place to store
the security context between user operations. In a typical web application, a user logs in

View File

@ -1,236 +0,0 @@
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="web-infrastructure"
xmlns:xlink="http://www.w3.org/1999/xlink">
<info>
<title>Web Application Infrastructure</title>
</info>
<para> Most Spring Security users will be using the framework in applications which make user of
the HTTP and the Servlet API. In this and the following chapters, 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>
<section xml:id="filters">
<title>Security Filter</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>
<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>
<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[
<filter>
<filter-name>myFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<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
<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[
<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
<sec:filter-chain-map path-type="ant">
<sec:filter-chain pattern="/webServices/**" filters="
securityContextPersistenceFilterWithASCFalse,
basicProcessingFilter,
exceptionTranslationFilter,
filterSecurityInterceptor" />
<sec:filter-chain pattern="/**" filters="
securityContextPersistenceFilterWithASCTrue,
authenticationProcessingFilter,
exceptionTranslationFilter,
filterSecurityInterceptor" />
</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>
<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>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="#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>
<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>
</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
inheritnum="ignore" continuation="restarts">
<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>UsernamePasswordAuthenticationProcessingFilter</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>
</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>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>
</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>
</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>
</section>
</section>
<!--
<section xml:id="taglib">
<info>
<title>Tag Libraries</title>
</info>
<para>Spring Security comes bundled with several JSP tag libraries which provide a range of
different services.</para>
<section xml:id="taglib-config">
<info>
<title>Configuration</title>
</info>
<para>All taglib classes are included in the core
<literal>spring-security-taglibs-&lt;version>.jar</literal> file, with the
<literal>security.tld</literal> located in the JAR's <literal>META-INF</literal>
directory. This means for JSP 1.2+ web containers you can simply include the JAR in the
WAR's <literal>WEB-INF/lib</literal> directory and it will be available.</para>
</section>
<section xml:id="taglib-usage">
<info>
<title>Usage</title>
</info>
<para>Now that you've configured the tag libraries, refer to the individual reference guide
sections for details on how to use them. Note that when using the tags, you should include
the taglib reference in your JSP:
<programlisting>
&lt;%@ taglib prefix='security' uri='http://www.springframework.org/security/tags' %&gt;
</programlisting></para>
</section>
</section>-->
</chapter>