SEC-1178: More ref manual updates
This commit is contained in:
parent
ff5b90ef9d
commit
65d83faef2
|
@ -117,10 +117,7 @@
|
||||||
<section xml:id="nsa-access-denied-page">
|
<section xml:id="nsa-access-denied-page">
|
||||||
<title><literal>access-denied-page</literal></title>
|
<title><literal>access-denied-page</literal></title>
|
||||||
<para>
|
<para>
|
||||||
Allows the access denied page to be set (the user will be redirected here if an
|
Deprecated in favour of the <literal>access-denied-handler</literal> child element.
|
||||||
<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>.
|
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
@ -145,6 +142,16 @@
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
</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>
|
<section>
|
||||||
<title>The <literal><intercept-url></literal> Element</title>
|
<title>The <literal><intercept-url></literal> Element</title>
|
||||||
|
|
|
@ -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>
|
|
@ -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>
|
|
|
@ -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><security:authentication property="principal.username"/></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>
|
|
|
@ -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>
|
|
|
@ -63,7 +63,5 @@
|
||||||
</note>
|
</note>
|
||||||
If authentication fails, the configured <interfacename>AuthenticationFailureHandler</interfacename> will be invoked.
|
If authentication fails, the configured <interfacename>AuthenticationFailureHandler</interfacename> will be invoked.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
|
@ -145,121 +145,4 @@ public void afterPropertiesSet() throws Exception {
|
||||||
whatever means you think fit (eg <literal>new Person();</literal>) and they will have the
|
whatever means you think fit (eg <literal>new Person();</literal>) and they will have the
|
||||||
security interceptor applied.</para>
|
security interceptor applied.</para>
|
||||||
</section>
|
</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><filter-security-metadata-source></literal> namespace element. This is
|
|
||||||
similar to the <literal><filter-chain-map></literal> used to configure a
|
|
||||||
<classname>FilterChainProxy</classname> but the <literal><intercept-url></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<ConfigAttribute></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>
|
</chapter>
|
||||||
|
|
|
@ -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-<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>
|
||||||
|
<%@ taglib prefix='security' uri='http://www.springframework.org/security/tags' %>
|
||||||
|
</programlisting></para>
|
||||||
|
</section>
|
||||||
|
</section>-->
|
||||||
|
</chapter>
|
|
@ -97,7 +97,24 @@
|
||||||
Security.</para>
|
Security.</para>
|
||||||
</partintro>
|
</partintro>
|
||||||
<xi:include href="technical-overview.xml"/>
|
<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>
|
||||||
<part xml:id="authentication">
|
<part xml:id="authentication">
|
||||||
<title>Authentication</title>
|
<title>Authentication</title>
|
||||||
|
@ -120,12 +137,7 @@
|
||||||
the project web site.</para>
|
the project web site.</para>
|
||||||
</footnote>. </para>
|
</footnote>. </para>
|
||||||
</partintro>
|
</partintro>
|
||||||
<xi:include href="common-auth-services.xml"/>
|
|
||||||
<xi:include href="dao-auth-provider.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="anon-auth-provider.xml"/>
|
||||||
<xi:include href="runas-auth-provider.xml"/>
|
<xi:include href="runas-auth-provider.xml"/>
|
||||||
</part>
|
</part>
|
||||||
|
@ -145,24 +157,21 @@
|
||||||
</partintro>
|
</partintro>
|
||||||
<xi:include href="authorization-common.xml"/>
|
<xi:include href="authorization-common.xml"/>
|
||||||
<xi:include href="secured-objects.xml"/>
|
<xi:include href="secured-objects.xml"/>
|
||||||
<xi:include href="domain-acls.xml"/>
|
|
||||||
</part>
|
</part>
|
||||||
<part xml:id="advanced-topics">
|
<part xml:id="advanced-topics">
|
||||||
<title>Advanced Topics</title>
|
<title>Advanced Topics</title>
|
||||||
<!--
|
<!--
|
||||||
Essentially standalone features which do not have to follow on directly from earlier chapters
|
Essentially standalone features which do not have to follow on directly from earlier chapters
|
||||||
-->
|
-->
|
||||||
<partintro>
|
<partintro>
|
||||||
<para>
|
<para> In this part we cover some of the more advanced features of the framework. </para>
|
||||||
In this part we cover some of the more advanced features of the framework.
|
|
||||||
</para>
|
|
||||||
</partintro>
|
</partintro>
|
||||||
<xi:include href="remember-me-authentication.xml"/>
|
<xi:include href="domain-acls.xml"/>
|
||||||
<xi:include href="preauth.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="jaas-auth-provider.xml"/>
|
||||||
<xi:include href="cas-auth-provider.xml"/>
|
<xi:include href="cas-auth-provider.xml"/>
|
||||||
<xi:include href="x509-auth-provider.xml"/>
|
<xi:include href="x509-auth-provider.xml"/>
|
||||||
</part>
|
</part>
|
||||||
<xi:include href="appendix-db-schema.xml"/>
|
<xi:include href="appendix-db-schema.xml"/>
|
||||||
<xi:include href="appendix-namespace.xml"/>
|
<xi:include href="appendix-namespace.xml"/>
|
||||||
|
|
|
@ -108,8 +108,8 @@ if (principal instanceof UserDetails) {
|
||||||
required.</para>
|
required.</para>
|
||||||
<para> On successful authentication, <interfacename>UserDetails</interfacename> is used to
|
<para> On successful authentication, <interfacename>UserDetails</interfacename> is used to
|
||||||
build the <interfacename>Authentication</interfacename> object that is stored in the
|
build the <interfacename>Authentication</interfacename> object that is stored in the
|
||||||
<classname>SecurityContextHolder</classname> (more on this in <link
|
<classname>SecurityContextHolder</classname> (more on this <link
|
||||||
xlink:href="#tech-intro-authentication-mgr"/> below). The good news is that we provide a
|
xlink:href="#tech-intro-authentication-mgr">below</link>). The good news is that we provide a
|
||||||
number of <interfacename>UserDetailsService</interfacename> implementations, including one
|
number of <interfacename>UserDetailsService</interfacename> implementations, including one
|
||||||
that uses an in-memory map (<classname>InMemoryDaoImpl</classname>) and another that uses
|
that uses an in-memory map (<classname>InMemoryDaoImpl</classname>) and another that uses
|
||||||
JDBC (<interfacename>JdbcDaoImpl</interfacename>). Most users tend to write their own,
|
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
|
(or equivalent) that reads the third-party user information from a location, build a
|
||||||
Spring Security-specific <interfacename>Authentication</interfacename> object, and put it
|
Spring Security-specific <interfacename>Authentication</interfacename> object, and put it
|
||||||
onto the <classname>SecurityContextHolder</classname>.</para>
|
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>
|
</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>
|
<section xml:id="tech-intro-web-authentication">
|
||||||
<title>Authentication in a Web Application</title>
|
<title>Authentication in a Web Application</title>
|
||||||
<para> Now let's explore the situation where you are using Spring Security in a web application
|
<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
|
(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
|
<interfacename>AuthenticationEntryPoint</interfacename> (if the principal has not been
|
||||||
authenticated and therefore we need to go commence step three).</para>
|
authenticated and therefore we need to go commence step three).</para>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="tech-auth-entry-point">
|
<section xml:id="tech-intro-auth-entry-point">
|
||||||
<title>AuthenticationEntryPoint</title>
|
<title>AuthenticationEntryPoint</title>
|
||||||
<para>The <interfacename>AuthenticationEntryPoint</interfacename> is responsible for step
|
<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
|
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
|
rejected the request, the authentication mechanism will ask the user agent to retry (step
|
||||||
two above).</para>
|
two above).</para>
|
||||||
</section>
|
</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>
|
<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
|
<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
|
the security context between user operations. In a typical web application, a user logs in
|
||||||
|
|
|
@ -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-<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>
|
|
||||||
<%@ taglib prefix='security' uri='http://www.springframework.org/security/tags' %>
|
|
||||||
</programlisting></para>
|
|
||||||
</section>
|
|
||||||
</section>-->
|
|
||||||
</chapter>
|
|
Loading…
Reference in New Issue