Updated docs to reflect changes for SEC-1259
This commit is contained in:
parent
80eb47c6fe
commit
73905b9ebd
|
@ -47,16 +47,17 @@
|
|||
principal. There is a corresponding <literal>AnonymousAuthenticationProvider</literal>,
|
||||
which is chained into the <literal>ProviderManager</literal> so that
|
||||
<literal>AnonymousAuthenticationToken</literal>s are accepted. Finally, there is an
|
||||
AnonymousProcessingFilter, which is chained after the normal authentication mechanisms
|
||||
and automatically adds an <literal>AnonymousAuthenticationToken</literal> to the
|
||||
<classname>AnonymousAuthenticationFilter</classname>, which is chained after the
|
||||
normal authentication mechanisms and automatically adds an
|
||||
<literal>AnonymousAuthenticationToken</literal> to the
|
||||
<classname>SecurityContextHolder</classname> if there is no existing
|
||||
<interfacename>Authentication</interfacename> held there. The definition of the
|
||||
filter and authentication provider appears as follows:</para>
|
||||
<para>
|
||||
<programlisting>
|
||||
<![CDATA[
|
||||
<bean id="anonymousProcessingFilter"
|
||||
class="org.springframework.security.web.authentication.AnonymousProcessingFilter">
|
||||
<bean id="anonymousAuthFilter"
|
||||
class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
|
||||
<property name="key" value="foobar"/>
|
||||
<property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
|
||||
</bean>
|
||||
|
@ -68,10 +69,10 @@
|
|||
</programlisting>
|
||||
</para>
|
||||
<para>The <literal>key</literal> is shared between the filter and authentication provider,
|
||||
so that tokens created by the former are accepted by the latter<footnote>
|
||||
<para>The use of the <literal>key</literal> property should not be regarded as
|
||||
providing any real security here. It is merely a book-keeping exercise. If you
|
||||
are sharing a <classname>ProviderManager</classname> which contains an
|
||||
so that tokens created by the former are accepted by the latter<footnote><para>The use
|
||||
of the <literal>key</literal> property should not be regarded as providing any
|
||||
real security here. It is merely a book-keeping exercise. If you are sharing a
|
||||
<classname>ProviderManager</classname> which contains an
|
||||
<classname>AnonymousAuthenticationProvider</classname> in a scenario where
|
||||
it is possible for an authenticating client to construct the
|
||||
<interfacename>Authentication</interfacename> object (such as with RMI
|
||||
|
@ -82,14 +83,15 @@
|
|||
anonymous provider. This isn't a problem with normal usage but if you are using
|
||||
RMI you would be best to use a customized <classname>ProviderManager</classname>
|
||||
which omits the anonymous provider rather than sharing the one you use for your
|
||||
HTTP authentication mechanisms.</para>
|
||||
</footnote>. The <literal>userAttribute</literal> is expressed in the form of
|
||||
HTTP authentication mechanisms.</para></footnote>. The
|
||||
<literal>userAttribute</literal> is expressed in the form of
|
||||
<literal>usernameInTheAuthenticationToken,grantedAuthority[,grantedAuthority]</literal>.
|
||||
This is the same syntax as used after the equals sign for
|
||||
<literal>InMemoryDaoImpl</literal>'s <literal>userMap</literal> property.</para>
|
||||
<para>As explained earlier, the benefit of anonymous authentication is that all URI patterns
|
||||
can have security applied to them. For example:</para>
|
||||
<para><programlisting>
|
||||
<para>
|
||||
<programlisting>
|
||||
<![CDATA[
|
||||
<bean id="filterSecurityInterceptor"
|
||||
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
|
||||
|
@ -105,31 +107,29 @@
|
|||
</security:filter-security-metadata-source>" +
|
||||
</property>
|
||||
</bean>]]>
|
||||
</programlisting></para>
|
||||
</programlisting>
|
||||
</para>
|
||||
</section>
|
||||
<section xml:id="anonymous-auth-trust-resolver">
|
||||
<title><interfacename>AuthenticationTrustResolver</interfacename></title>
|
||||
<para>
|
||||
Rounding out the anonymous authentication discussion is the
|
||||
<interfacename>AuthenticationTrustResolver</interfacename> interface, with its corresponding
|
||||
<literal>AuthenticationTrustResolverImpl</literal> implementation. This interface
|
||||
provides an <literal>isAnonymous(Authentication)</literal> method, which allows
|
||||
interested classes to take into account this special type of authentication status. The
|
||||
<classname>ExceptionTranslationFilter</classname> uses this interface in processing
|
||||
<literal>AccessDeniedException</literal>s. If an
|
||||
<literal>AccessDeniedException</literal> is thrown, and the authentication is of an
|
||||
<para> Rounding out the anonymous authentication discussion is the
|
||||
<interfacename>AuthenticationTrustResolver</interfacename> interface, with its
|
||||
corresponding <literal>AuthenticationTrustResolverImpl</literal> implementation. This
|
||||
interface provides an <literal>isAnonymous(Authentication)</literal> method, which
|
||||
allows interested classes to take into account this special type of authentication
|
||||
status. The <classname>ExceptionTranslationFilter</classname> uses this interface in
|
||||
processing <literal>AccessDeniedException</literal>s. If an
|
||||
<literal>AccessDeniedException</literal> is thrown, and the authentication is of an
|
||||
anonymous type, instead of throwing a 403 (forbidden) response, the filter will instead
|
||||
commence the <interfacename>AuthenticationEntryPoint</interfacename> so the principal
|
||||
can authenticate properly. This is a necessary distinction, otherwise principals would
|
||||
always be deemed <quote>authenticated</quote> and never be given an opportunity to login
|
||||
via form, basic, digest or some other normal authentication mechanism.
|
||||
</para>
|
||||
<para>
|
||||
You will often see the <literal>ROLE_ANONYMOUS</literal> attribute in the above interceptor configuration
|
||||
replaced with <literal>IS_AUTHENTICATED_ANONYMOUSLY</literal>. This is an example of the use of the
|
||||
<classname>AuthenticatedVoter</classname> which will see in ???. It uses an
|
||||
<interfacename>AuthenticationTrustResolver</interfacename> to process this particular configuration
|
||||
attribute and grant access to aonymous users.
|
||||
via form, basic, digest or some other normal authentication mechanism. </para>
|
||||
<para> You will often see the <literal>ROLE_ANONYMOUS</literal> attribute in the above
|
||||
interceptor configuration replaced with <literal>IS_AUTHENTICATED_ANONYMOUSLY</literal>.
|
||||
This is an example of the use of the <classname>AuthenticatedVoter</classname> which
|
||||
will see in ???. It uses an <interfacename>AuthenticationTrustResolver</interfacename>
|
||||
to process this particular configuration attribute and grant access to aonymous users.
|
||||
</para>
|
||||
</section>
|
||||
</chapter>
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
<title><literal>realm</literal></title>
|
||||
<para> Sets the realm name used for basic authentication (if enabled). Corresponds to the
|
||||
<literal>realmName</literal> proerty on
|
||||
<classname>BasicProcessingFilterEntryPoint</classname>. </para>
|
||||
<classname>BasicAuthenticationEntryPoint</classname>. </para>
|
||||
</section>
|
||||
<section xml:id="nsa-entry-point-ref">
|
||||
<title><literal>entry-point-ref</literal></title>
|
||||
|
@ -123,7 +123,7 @@
|
|||
<interfacename>FilterInvocationDefinitionSource</interfacename> used by the
|
||||
<classname>FilterSecurityInterceptor</classname> and to exclude particular patterns from
|
||||
the filter chain entirely (by setting the attribute <literal>filters="none"</literal>). It
|
||||
is also responsible for configuring a <classname>ChannelProcessingFilter</classname> if
|
||||
is also responsible for configuring a <classname>ChannelAuthenticationFilter</classname> if
|
||||
particular URLs need to be accessed by HTTPS, for example. </para>
|
||||
<section xml:id="nsa-pattern">
|
||||
<title><literal>pattern</literal></title>
|
||||
|
@ -149,8 +149,8 @@
|
|||
accessed over HTTP or HTTPS respectively. Alternatively the value "any" can be used when
|
||||
there is no preference. If this attribute is present on any
|
||||
<literal><intercept-url></literal> element, then a
|
||||
<classname>ChannelProcessingFilter</classname> will be added to the filter stack and its
|
||||
additional dependencies added to the application context.
|
||||
<classname>ChannelAuthenticationFilter</classname> will be added to the filter stack and
|
||||
its additional dependencies added to the application context.
|
||||
<!--See the chapter on <link
|
||||
xlink:href="#channel-security-config">channel security</link> for an example
|
||||
configuration using traditional beans. --></para>
|
||||
|
@ -237,15 +237,14 @@
|
|||
</section>
|
||||
<section xml:id="nsa-http-basic">
|
||||
<title>The <literal><http-basic></literal> Element</title>
|
||||
<para> Adds a <classname>BasicProcessingFilter</classname> and
|
||||
<classname>BasicProcessingFilterEntryPoint</classname> to the configuration. The latter
|
||||
will only be used as the configuration entry point if form-based login is not enabled.
|
||||
</para>
|
||||
<para> Adds a <classname>BasicAuthenticationFilter</classname> and
|
||||
<classname>BasicAuthenticationEntryPoint</classname> to the configuration. The latter will
|
||||
only be used as the configuration entry point if form-based login is not enabled. </para>
|
||||
</section>
|
||||
<section xml:id="nsa-remember-me">
|
||||
<title>The <literal><remember-me></literal> Element</title>
|
||||
<para> Adds the <classname>RememberMeProcessingFilter</classname> to the stack. This in turn
|
||||
will be configured with either a <classname>TokenBasedRememberMeServices</classname>, a
|
||||
<para> Adds the <classname>RememberMeAuthenticationFilter</classname> to the stack. This in
|
||||
turn will be configured with either a <classname>TokenBasedRememberMeServices</classname>, a
|
||||
<classname>PersistentTokenBasedRememberMeServices</classname> or a user-specified bean
|
||||
implementing <interfacename>RememberMeServices</interfacename> depending on the attribute
|
||||
settings. </para>
|
||||
|
@ -354,17 +353,17 @@
|
|||
</section>
|
||||
<section xml:id="nsa-anonymous">
|
||||
<title>The <literal><anonymous></literal> Element</title>
|
||||
<para> Adds an <classname>AnonymousProcessingFilter</classname> to the stack and an
|
||||
<para> Adds an <classname>AnonymousAuthenticationFilter</classname> to the stack and an
|
||||
<classname>AnonymousAuthenticationProvider</classname>. Required if you are using the
|
||||
<literal>IS_AUTHENTICATED_ANONYMOUSLY</literal> attribute. </para>
|
||||
</section>
|
||||
<section xml:id="nsa-x509">
|
||||
<title>The <literal><x509></literal> Element</title>
|
||||
<para> Adds support for X.509 authentication. An
|
||||
<classname>X509PreAuthenticatedProcessingFilter</classname> will be added to the stack and
|
||||
a <classname>PreAuthenticatedProcessingFilterEntryPoint</classname> bean will be created.
|
||||
The latter will only be used if no other authentication mechanisms are in use (it's only
|
||||
functionality is to return an HTTP 403 error code). A
|
||||
<classname>X509AuthenticationFilter</classname> will be added to the stack and an
|
||||
<classname>Http403ForbiddenEntryPoint</classname> bean will be created. The latter will
|
||||
only be used if no other authentication mechanisms are in use (it's only functionality is to
|
||||
return an HTTP 403 error code). A
|
||||
<classname>PreAuthenticatedAuthenticationProvider</classname> will also be created which
|
||||
delegates the loading of user authorities to a
|
||||
<interfacename>UserDetailsService</interfacename>. </para>
|
||||
|
|
|
@ -4,20 +4,21 @@
|
|||
</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>
|
||||
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>
|
||||
<title><classname>BasicAuthenticationFilter</classname></title>
|
||||
</info>
|
||||
<para><literal>BasicProcessingFilter</literal> is responsible for processing basic
|
||||
<para><literal>BasicAuthenticationFilter</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
|
||||
<literal>BasicAuthenticationFilter</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>
|
||||
|
@ -26,51 +27,50 @@
|
|||
<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>
|
||||
<literal>BasicAuthenticationFilter</literal> to your filter chain. The
|
||||
application context should contain <literal>BasicAuthenticationFilter</literal> and
|
||||
its required collaborator:</para>
|
||||
<para>
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<bean id="basicProcessingFilter"
|
||||
class="org.springframework.security.web.authentication.www.BasicProcessingFilter">
|
||||
<bean id="basicAuthenticationFilter"
|
||||
class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
|
||||
<property name="authenticationManager" ref="authenticationManager"/>
|
||||
<property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
|
||||
</bean>
|
||||
|
||||
<bean id="authenticationEntryPoint"
|
||||
class="org.springframework.security.web.authentication.www.BasicProcessingFilterEntryPoint">
|
||||
class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint">
|
||||
<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
|
||||
<interfacename>AuthenticationEntryPoint</interfacename> will be used to retry
|
||||
the authentication process. Usually you will use the filter in combination with a
|
||||
<literal>BasicAuthenticationEntryPoint</literal>, which returns a 401 response
|
||||
with a suitable header to retry HTTP Basic authentication. If authentication is
|
||||
successful, the resulting <interfacename>Authentication</interfacename> object will be
|
||||
placed into the <classname>SecurityContextHolder</classname> as usual.</para>
|
||||
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>
|
||||
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
|
||||
<title><classname>DigestAuthenticationFilter</classname></title>
|
||||
<para><classname>DigestAuthenticationFilter</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>DigestAuthenticationFilter</classname> is
|
||||
compatible with the "<literal>auth</literal>" quality of protection
|
||||
(<literal>qop</literal>) prescribed by RFC 2617, which also provides backward
|
||||
(<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
|
||||
|
@ -88,9 +88,9 @@
|
|||
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
|
||||
<para>The <classname>DigestAuthenticatonEntryPoint</classname> has a property specifying the
|
||||
<literal>key</literal> used for generating the nonce tokens, along with a
|
||||
<literal>nonceValiditySeconds</literal> property for determining the expiration time
|
||||
(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
|
||||
|
@ -98,12 +98,12 @@
|
|||
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
|
||||
the <classname>DigestAuthenticationEntryPoint</classname> will send a
|
||||
<literal>"stale=true"</literal> header. This tells the user agent there is no need
|
||||
to disturb the user (as the password and username etc is correct), but simply to try
|
||||
again using a new nonce.</para>
|
||||
<para>An appropriate value for <classname>DigestProcessingFilterEntryPoint</classname>'s
|
||||
<literal>nonceValiditySeconds</literal> parameter will depend on your application.
|
||||
<para>An appropriate value for <classname>DigestAuthenticationEntryPoint</classname>'s
|
||||
<literal>nonceValiditySeconds</literal> parameter will depend on your application.
|
||||
Extremely secure applications should note that an intercepted authentication header can
|
||||
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
|
||||
|
@ -111,28 +111,30 @@
|
|||
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
|
||||
"<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
|
||||
"<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>
|
||||
<title>Configuration</title>
|
||||
<para>Now that we've reviewed the theory, let's see how to use it. To implement HTTP
|
||||
Digest Authentication, it is necessary to define
|
||||
<literal>DigestAuthenticationFilter</literal> in the filter chain. The
|
||||
application context will need to define the
|
||||
<literal>DigestAuthenticationFilter</literal> and its required
|
||||
collaborators:</para>
|
||||
<para>
|
||||
<programlisting><![CDATA[
|
||||
<bean id="digestProcessingFilter" class=
|
||||
"org.springframework.security.web.authentication.www.DigestProcessingFilter">
|
||||
<bean id="digestFilter" class=
|
||||
"org.springframework.security.web.authentication.www.DigestAuthenticationFilter">
|
||||
<property name="userDetailsService" ref="jdbcDaoImpl"/>
|
||||
<property name="authenticationEntryPoint" ref="digestProcessingFilterEntryPoint"/>
|
||||
<property name="authenticationEntryPoint" ref="digestEntryPoint"/>
|
||||
<property name="userCache" ref="userCache"/>
|
||||
</bean>
|
||||
|
||||
<bean id="digestProcessingFilterEntryPoint" class=
|
||||
"org.springframework.security.web.authentication.www.DigestProcessingFilterEntryPoint">
|
||||
<bean id="digestEntryPoint" class=
|
||||
"org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint">
|
||||
<property name="realmName" value="Contacts Realm via Digest Authentication"/>
|
||||
<property name="key" value="acegi"/>
|
||||
<property name="nonceValiditySeconds" value="10"/>
|
||||
|
@ -140,31 +142,31 @@
|
|||
</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
|
||||
<literal>DigestAuthenticationFilter</literal> must have direct access to the
|
||||
clear text password of a user. Digest Authentication will NOT work if you are using
|
||||
encoded passwords in your DAO. The DAO collaborator, along with the
|
||||
<literal>UserCache</literal>, are typically shared directly with a
|
||||
<classname>DaoAuthenticationProvider</classname>. The
|
||||
<literal>authenticationEntryPoint</literal> property must be
|
||||
<classname>DigestAuthenticationEntryPoint</classname>, so that
|
||||
<classname>DigestAuthenticationFilter</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>
|
||||
<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 +1,44 @@
|
|||
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="cas"
|
||||
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="cas"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
|
||||
<title>CAS Authentication</title>
|
||||
|
||||
<section xml:id="cas-overview">
|
||||
<title>Overview</title>
|
||||
|
||||
<para>JA-SIG produces an enterprise-wide single sign on system known
|
||||
as CAS. Unlike other initiatives, JA-SIG's Central Authentication
|
||||
Service is open source, widely used, simple to understand, platform
|
||||
independent, and supports proxy capabilities. Spring Security fully
|
||||
supports CAS, and provides an easy migration path from
|
||||
single-application deployments of Spring Security through to
|
||||
multiple-application deployments secured by an enterprise-wide CAS
|
||||
server.</para>
|
||||
|
||||
<para>You can learn more about CAS at
|
||||
<literal>http://www.ja-sig.org/products/cas/</literal>. You will also need
|
||||
to visit this site to download the CAS Server files.</para>
|
||||
<para>JA-SIG produces an enterprise-wide single sign on system known as CAS. Unlike other
|
||||
initiatives, JA-SIG's Central Authentication Service is open source, widely used, simple to
|
||||
understand, platform independent, and supports proxy capabilities. Spring Security fully
|
||||
supports CAS, and provides an easy migration path from single-application deployments of
|
||||
Spring Security through to multiple-application deployments secured by an enterprise-wide CAS
|
||||
server.</para>
|
||||
<para>You can learn more about CAS at <literal>http://www.ja-sig.org/products/cas/</literal>.
|
||||
You will also need to visit this site to download the CAS Server files.</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="cas-how-it-works">
|
||||
<info><title>How CAS Works</title></info>
|
||||
|
||||
<para>Whilst the CAS web site contains documents that detail
|
||||
the architecture of CAS, we present the general overview again here
|
||||
within the context of Spring Security. Spring Security 2.0 supports
|
||||
CAS 3. At the time of writing, the CAS server was at version 3.2.</para>
|
||||
|
||||
<para>Somewhere in your enterprise you will need to setup a CAS
|
||||
server. The CAS server is simply a standard WAR file, so there isn't
|
||||
anything difficult about setting up your server. Inside the WAR file
|
||||
you will customise the login and other single sign on pages displayed
|
||||
to users.</para>
|
||||
|
||||
<info>
|
||||
<title>How CAS Works</title>
|
||||
</info>
|
||||
<para>Whilst the CAS web site contains documents that detail the architecture of CAS, we present
|
||||
the general overview again here within the context of Spring Security. Spring Security 2.0
|
||||
supports CAS 3. At the time of writing, the CAS server was at version 3.2.</para>
|
||||
<para>Somewhere in your enterprise you will need to setup a CAS server. The CAS server is simply
|
||||
a standard WAR file, so there isn't anything difficult about setting up your server. Inside
|
||||
the WAR file you will customise the login and other single sign on pages displayed to
|
||||
users.</para>
|
||||
<para>When deploying a CAS 3.2 server, you will also need to specify an
|
||||
<literal>AuthenticationHandler</literal> in the
|
||||
<filename>deployerConfigContext.xml</filename> included with CAS. The
|
||||
<literal>AuthenticationHandler</literal> has a simple method that
|
||||
returns a boolean as to whether a given set of Credentials is valid.
|
||||
Your <literal>AuthenticationHandler</literal> implementation will need
|
||||
to link into some type of backend authentication repository, such as
|
||||
an LDAP server or database. CAS itself includes numerous
|
||||
<literal>AuthenticationHandler</literal>s out of the box to assist
|
||||
with this. When you download and deploy the server war file, it is set up
|
||||
to successfully authenticate users who enter a password matching their
|
||||
username, which is useful for testing.</para>
|
||||
|
||||
<para>Apart from the CAS server itself, the other key players are of
|
||||
course the secure web applications deployed throughout your
|
||||
enterprise. These web applications are known as "services". There are
|
||||
two types of services: standard services and proxy services. A proxy
|
||||
service is able to request resources from other services on behalf of
|
||||
the user. This will be explained more fully later.</para>
|
||||
|
||||
<!--
|
||||
<literal>AuthenticationHandler</literal> in the
|
||||
<filename>deployerConfigContext.xml</filename> included with CAS. The
|
||||
<literal>AuthenticationHandler</literal> has a simple method that returns a boolean as to
|
||||
whether a given set of Credentials is valid. Your <literal>AuthenticationHandler</literal>
|
||||
implementation will need to link into some type of backend authentication repository, such as
|
||||
an LDAP server or database. CAS itself includes numerous
|
||||
<literal>AuthenticationHandler</literal>s out of the box to assist with this. When you
|
||||
download and deploy the server war file, it is set up to successfully authenticate users who
|
||||
enter a password matching their username, which is useful for testing.</para>
|
||||
<para>Apart from the CAS server itself, the other key players are of course the secure web
|
||||
applications deployed throughout your enterprise. These web applications are known as
|
||||
"services". There are two types of services: standard services and proxy services. A proxy
|
||||
service is able to request resources from other services on behalf of the user. This will be
|
||||
explained more fully later.</para>
|
||||
<!--
|
||||
<section xml:id="cas-sequence">
|
||||
<title>Spring Security and CAS Interaction Sequence</title>
|
||||
|
||||
|
@ -260,84 +244,69 @@
|
|||
</section>
|
||||
-->
|
||||
</section>
|
||||
|
||||
<section xml:id="cas-client">
|
||||
<info><title>Configuration of CAS Client</title></info>
|
||||
|
||||
<para>The web application side of CAS is made easy due to Spring
|
||||
Security. It is assumed you already know the basics of using Spring
|
||||
Security, so these are not covered again below. We'll assume a namespace
|
||||
based configuration is being used and add in the CAS beans as required.
|
||||
</para>
|
||||
|
||||
<para>You will need to add a <literal>ServiceProperties</literal> bean
|
||||
to your application context. This represents your service:</para>
|
||||
|
||||
<para><programlisting><![CDATA[
|
||||
<info>
|
||||
<title>Configuration of CAS Client</title>
|
||||
</info>
|
||||
<para>The web application side of CAS is made easy due to Spring Security. It is assumed you
|
||||
already know the basics of using Spring Security, so these are not covered again below. We'll
|
||||
assume a namespace based configuration is being used and add in the CAS beans as required. </para>
|
||||
<para>You will need to add a <literal>ServiceProperties</literal> bean to your application
|
||||
context. This represents your service:</para>
|
||||
<para>
|
||||
<programlisting><![CDATA[
|
||||
<bean id="serviceProperties"
|
||||
class="org.springframework.security.cas.ServiceProperties">
|
||||
<property name="service"
|
||||
value="https://localhost:8443/cas-sample/j_spring_cas_security_check"/>
|
||||
<property name="sendRenew" value="false"/>
|
||||
</bean>]]>
|
||||
</programlisting></para>
|
||||
|
||||
<para>The <literal>service</literal> must equal a URL that will be
|
||||
monitored by the <literal>CasProcessingFilter</literal>. The
|
||||
<literal>sendRenew</literal> defaults to false, but should be set to
|
||||
true if your application is particularly sensitive. What this
|
||||
parameter does is tell the CAS login service that a single sign on
|
||||
login is unacceptable. Instead, the user will need to re-enter their
|
||||
username and password in order to gain access to the service.</para>
|
||||
|
||||
<para>The following beans should be configured to commence the CAS
|
||||
authentication process:</para>
|
||||
|
||||
<para><programlisting><![CDATA[
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>The <literal>service</literal> must equal a URL that will be monitored by the
|
||||
<literal>CasAuthenticationFilter</literal>. The <literal>sendRenew</literal> defaults to
|
||||
false, but should be set to true if your application is particularly sensitive. What this
|
||||
parameter does is tell the CAS login service that a single sign on login is unacceptable.
|
||||
Instead, the user will need to re-enter their username and password in order to gain access to
|
||||
the service.</para>
|
||||
<para>The following beans should be configured to commence the CAS authentication
|
||||
process:</para>
|
||||
<para>
|
||||
<programlisting><![CDATA[
|
||||
<security:authentication-manager alias="authenticationManager"/>
|
||||
|
||||
<bean id="casProcessingFilter"
|
||||
class="org.springframework.security.cas.web.CasProcessingFilter">
|
||||
<bean id="casFilter"
|
||||
class="org.springframework.security.cas.web.CasAuthenticationFilter">
|
||||
<security:custom-filter after="CAS_PROCESSING_FILTER"/>
|
||||
<property name="authenticationManager" ref="authenticationManager"/>
|
||||
<property name="authenticationFailureUrl" value="/casfailed.jsp"/>
|
||||
<property name="defaultTargetUrl" value="/"/>
|
||||
</bean>
|
||||
|
||||
<bean id="casProcessingFilterEntryPoint"
|
||||
class="org.springframework.security.cas.web.CasProcessingFilterEntryPoint">
|
||||
<bean id="casEntryPoint"
|
||||
class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
|
||||
<property name="loginUrl" value="https://localhost:9443/cas/login"/>
|
||||
<property name="serviceProperties" ref="serviceProperties"/>
|
||||
</bean>
|
||||
]]>
|
||||
|
||||
</programlisting></para>
|
||||
|
||||
<para>
|
||||
The <classname>CasProcessingFilterEntryPoint</classname> should be selected to
|
||||
drive authentication using <link xlink:href="ns-entry-point-ref"><literal>entry-point-ref</literal></link>.
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
<para>The <literal>CasProcessingFilter</literal> has very similar
|
||||
properties to the <literal>UsernamePasswordAuthenticationFilter</literal>
|
||||
(used for form-based logins). Each property is
|
||||
self-explanatory. Note that we've also used the namespace syntax
|
||||
for setting up an alias to the authentication mnager, since the
|
||||
<literal>CasProcessingFilter</literal> needs a reference to it.</para>
|
||||
|
||||
<para>For CAS to operate, the
|
||||
<classname>ExceptionTranslationFilter</classname> must have its
|
||||
<literal>authenticationEntryPoint</literal> property set to the
|
||||
<literal>CasProcessingFilterEntryPoint</literal> bean.</para>
|
||||
|
||||
<para>The <literal>CasProcessingFilterEntryPoint</literal> must refer
|
||||
to the <literal>ServiceProperties</literal> bean (discussed above),
|
||||
which provides the URL to the enterprise's CAS login server. This is
|
||||
where the user's browser will be redirected.</para>
|
||||
|
||||
<para>Next you need to add a <literal>CasAuthenticationProvider</literal> and its
|
||||
collaborators:
|
||||
<programlisting><![CDATA[
|
||||
<para> The <classname>CasAuthenticationEntryPoint</classname> should be selected to drive
|
||||
authentication using <link xlink:href="ns-entry-point-ref"
|
||||
><literal>entry-point-ref</literal></link>. </para>
|
||||
<para>The <literal>CasAuthenticationFilter</literal> has very similar properties to the
|
||||
<literal>UsernamePasswordAuthenticationFilter</literal> (used for form-based logins). Each
|
||||
property is self-explanatory. Note that we've also used the namespace syntax for setting up an
|
||||
alias to the authentication mnager, since the <literal>CasAuthenticationFilter</literal> needs
|
||||
a reference to it.</para>
|
||||
<para>For CAS to operate, the <classname>ExceptionTranslationFilter</classname> must have its
|
||||
<literal>authenticationEntryPoint</literal> property set to the
|
||||
<literal>CasAuthenticationEntryPoint</literal> bean.</para>
|
||||
<para>The <literal>CasAuthenticationEntryPoint</literal> must refer to the
|
||||
<literal>ServiceProperties</literal> bean (discussed above), which provides the URL to the
|
||||
enterprise's CAS login server. This is where the user's browser will be redirected.</para>
|
||||
<para>Next you need to add a <literal>CasAuthenticationProvider</literal> and its collaborators: <programlisting><![CDATA[
|
||||
<bean id="casAuthenticationProvider"
|
||||
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
|
||||
<security:custom-authentication-provider />
|
||||
|
@ -355,16 +324,14 @@
|
|||
<security:user name="joe" password="joe" authorities="ROLE_USER" />
|
||||
...
|
||||
</security:user-service>]]>
|
||||
</programlisting>
|
||||
The <classname>CasAuthenticationProvider</classname> uses a <interfacename>UserDetailsService</interfacename>
|
||||
instance to load the authorities for a user, once they have been authentiated by CAS. We've shown a simple
|
||||
in-memory setup here.
|
||||
</para>
|
||||
|
||||
<para>The beans are all reasonable self-explanatory if you refer back
|
||||
to the "How CAS Works" section.</para>
|
||||
</programlisting> The
|
||||
<classname>CasAuthenticationProvider</classname> uses a
|
||||
<interfacename>UserDetailsService</interfacename> instance to load the authorities for a
|
||||
user, once they have been authentiated by CAS. We've shown a simple in-memory setup here. </para>
|
||||
<para>The beans are all reasonable self-explanatory if you refer back to the "How CAS Works"
|
||||
section.</para>
|
||||
</section>
|
||||
<!--
|
||||
<!--
|
||||
<para>Note the <literal>CasProxyTicketValidator</literal> has a
|
||||
remarked out <literal>trustStore</literal> property. This property
|
||||
might be helpful if you experience HTTPS certificate issues. Also note
|
||||
|
@ -462,4 +429,4 @@
|
|||
|
||||
</section>
|
||||
-->
|
||||
</chapter>
|
||||
</chapter>
|
||||
|
|
|
@ -250,15 +250,15 @@ class="org.springframework.security.web.context.SecurityContextPersistenceFilter
|
|||
<classname>ExceptionTranslationFilter</classname>.
|
||||
</para></listitem><listitem><para>Implement the login page (using a JSP or
|
||||
MVC controller).</para></listitem><listitem><para>Configure an instance of
|
||||
<classname>UsernamePasswordAuthenticationFilter</classname> in
|
||||
the application context</para></listitem><listitem><para>Add the filter bean
|
||||
to your filter chain proxy (making sure you pay attention to the order).
|
||||
<classname>UsernamePasswordAuthenticationFilter</classname> in the
|
||||
application context</para></listitem><listitem><para>Add the filter bean to
|
||||
your filter chain proxy (making sure you pay attention to the order).
|
||||
<!-- TODO: link --></para></listitem></orderedlist> The login form simply
|
||||
contains <literal>j_username</literal> and <literal>j_password</literal> input fields,
|
||||
and posts to the URL that is monitored by the filter (by default this is
|
||||
<literal>/j_spring_security_check</literal>). The basic filter configuration looks
|
||||
something like this: <programlisting><![CDATA[
|
||||
<bean id="authenticationProcessingFilter" class=
|
||||
<bean id="authenticationFilter" class=
|
||||
"org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
|
||||
<property name="authenticationManager" ref="authenticationManager"/>
|
||||
<property name="filterProcessesUrl" value="/j_spring_security_check"/>
|
||||
|
|
|
@ -188,7 +188,7 @@
|
|||
authentication and logout handling services respectively <footnote><para>In versions prior
|
||||
to 3.0, this list also included remember-me functionality. This could cause some
|
||||
confusing errors with some configurations and was removed in 3.0. In 3.0, the addition
|
||||
of an <classname>AnonymousProcessingFilter</classname> is part of the default
|
||||
of an <classname>AnonymousAuthenticationFilter</classname> is part of the default
|
||||
<literal><http></literal> configuration, so the <literal><anonymous
|
||||
/></literal> element is added regardless of whether <literal>auto-config</literal>
|
||||
is enabled.</para></footnote> . They each have attributes which can be used to alter
|
||||
|
@ -472,39 +472,37 @@
|
|||
align="center">Alias</entry><entry align="center">Filter Class</entry><entry
|
||||
align="center">Namespace Element or
|
||||
Attribute</entry></row></thead><tbody><row><entry>
|
||||
CHANNEL_FILTER</entry><entry><literal>ChannelProcessingFilter</literal></entry><entry><literal>http/intercept-url</literal></entry></row><row><entry>
|
||||
CHANNEL_FILTER</entry><entry><literal>ChannelProcessingFilter</literal></entry><entry><literal>http/intercept-url@requires-channel</literal></entry></row><row><entry>
|
||||
CONCURRENT_SESSION_FILTER</entry><entry><literal>ConcurrentSessionFilter</literal>
|
||||
</entry><entry><literal>http/concurrent-session-control</literal></entry></row><row><entry>
|
||||
SESSION_CONTEXT_INTEGRATION_FILTER</entry><entry><classname>HttpSessionContextIntegrationFilter</classname></entry><entry><literal>http</literal></entry></row><row><entry>
|
||||
</entry><entry><literal>session-management/concurrency-control</literal></entry></row><row><entry>
|
||||
SECURITY_CONTEXT_FILTER</entry><entry><classname>SecurityContextPersistenceFilter</classname></entry><entry><literal>http</literal></entry></row><row><entry>
|
||||
LOGOUT_FILTER
|
||||
</entry><entry><literal>LogoutFilter</literal></entry><entry><literal>http/logout</literal></entry></row><row><entry>
|
||||
X509_FILTER
|
||||
</entry><entry><literal>X509PreAuthenticatedProcessigFilter</literal></entry><entry><literal>http/x509</literal></entry></row><row><entry>
|
||||
</entry><entry><literal>X509AuthenticationFilter</literal></entry><entry><literal>http/x509</literal></entry></row><row><entry>
|
||||
PRE_AUTH_FILTER
|
||||
</entry><entry><literal>AstractPreAuthenticatedProcessingFilter</literal>
|
||||
Subclasses</entry><entry>N/A</entry></row><row><entry> CAS_PROCESSING_FILTER
|
||||
</entry><entry><literal>CasProcessingFilter</literal></entry><entry>N/A</entry></row><row><entry>
|
||||
AUTHENTICATION_PROCESSING_FILTER
|
||||
Subclasses</entry><entry>N/A</entry></row><row><entry> CAS_FILTER
|
||||
</entry><entry><literal>CasAuthenticationFilter</literal></entry><entry>N/A</entry></row><row><entry>
|
||||
FORM_LOGIN_FILTER
|
||||
</entry><entry><literal>UsernamePasswordAuthenticationFilter</literal></entry><entry><literal>http/form-login</literal></entry></row><row><entry>
|
||||
BASIC_PROCESSING_FILTER
|
||||
</entry><entry><literal>BasicProcessingFilter</literal></entry><entry><literal>http/http-basic</literal></entry></row><row><entry>
|
||||
SERVLET_API_SUPPORT_FILTER</entry><entry><literal>SecurityContextHolderAwareRequestFilter</literal></entry><entry><literal>http/@servlet-api-provision</literal></entry></row><row><entry>
|
||||
BASIC_AUTH_FILTER
|
||||
</entry><entry><literal>BasicAuthenticationFilter</literal></entry><entry><literal>http/http-basic</literal></entry></row><row><entry>
|
||||
SERVLET_API_SUPPORT_FILTER</entry><entry><literal>SecurityContextHolderAwareFilter</literal></entry><entry><literal>http/@servlet-api-provision</literal></entry></row><row><entry>
|
||||
REMEMBER_ME_FILTER
|
||||
</entry><entry><classname>RememberMeProcessingFilter</classname></entry><entry><literal>http/remember-me</literal></entry></row><row><entry>
|
||||
</entry><entry><classname>RememberMeAuthenticationFilter</classname></entry><entry><literal>http/remember-me</literal></entry></row><row><entry>
|
||||
ANONYMOUS_FILTER
|
||||
</entry><entry><literal>AnonymousProcessingFilter</literal></entry><entry><literal>http/anonymous</literal></entry></row><row><entry>
|
||||
EXCEPTION_TRANSLATION_FILTER
|
||||
</entry><entry><literal>AnonymousAuthenticationFilter</literal></entry><entry><literal>http/anonymous</literal></entry></row><row><entry>
|
||||
SESSION_MANAGEMENT_FILTER</entry><entry><literal>SessionManagementFilter</literal></entry><entry><literal>session-management</literal></entry></row><row><entry>EXCEPTION_TRANSLATION_FILTER
|
||||
</entry><entry><classname>ExceptionTranslationFilter</classname></entry><entry><literal>http</literal></entry></row><row><entry>
|
||||
NTLM_FILTER
|
||||
</entry><entry><literal>NtlmProcessingFilter</literal></entry><entry>N/A</entry></row><row><entry>
|
||||
FILTER_SECURITY_INTERCEPTOR
|
||||
</entry><entry><classname>FilterSecurityInterceptor</classname></entry><entry><literal>http</literal></entry></row><row><entry>
|
||||
SWITCH_USER_FILTER
|
||||
</entry><entry><literal>SwitchUserProcessingFilter</literal></entry><entry>N/A</entry></row></tbody></tgroup></table>
|
||||
</entry><entry><literal>SwitchUserFilter</literal></entry><entry>N/A</entry></row></tbody></tgroup></table>
|
||||
You can add your own filter to the stack, using the <literal>custom-filter</literal> element
|
||||
and one of these names to specify the position your filter should appear at: <programlisting language="xml"><![CDATA[
|
||||
<http>
|
||||
<custom-filter position="AUTHENTICATION_PROCESSING_FILTER" ref="myFilter" />
|
||||
<custom-filter position="FORM_LOGIN_FILTER" ref="myFilter" />
|
||||
</http>
|
||||
|
||||
<beans:bean id="myFilter" class="com.mycompany.MySpecialAuthenticationFilter"/>
|
||||
|
|
|
@ -8,150 +8,137 @@
|
|||
has already been reliably authenticated by some external system prior to accessing the
|
||||
application. We refer to these situations as <quote>pre-authenticated</quote> scenarios.
|
||||
Examples include X.509, Siteminder and authentication by the J2EE container in which the
|
||||
application is running. When using pre-authentication, Spring Security has to
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
<para>Identify the user making the request. </para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Obtain the authorities for the user.</para>
|
||||
</listitem>
|
||||
</orderedlist>The details will depend on the external authentication mechanism. A user might be
|
||||
identified by their certificate information in the case of X.509, or by an HTTP request header
|
||||
in the case of Siteminder. If relying on container authentication, the user will be identified
|
||||
by calling the <methodname>getUserPrincipal()</methodname> method on the incoming HTTP request.
|
||||
In some cases, the external mechanism may supply role/authority information for the user but in
|
||||
others the authorities must be obtained from a separate source, such as a
|
||||
<interfacename>UserDetailsService</interfacename>.
|
||||
</para>
|
||||
application is running. When using pre-authentication, Spring Security has to
|
||||
<orderedlist><listitem><para>Identify the user making the request.
|
||||
</para></listitem><listitem><para>Obtain the authorities for the
|
||||
user.</para></listitem></orderedlist>The details will depend on the external authentication
|
||||
mechanism. A user might be identified by their certificate information in the case of X.509, or
|
||||
by an HTTP request header in the case of Siteminder. If relying on container authentication, the
|
||||
user will be identified by calling the <methodname>getUserPrincipal()</methodname> method on the
|
||||
incoming HTTP request. In some cases, the external mechanism may supply role/authority
|
||||
information for the user but in others the authorities must be obtained from a separate source,
|
||||
such as a <interfacename>UserDetailsService</interfacename>. </para>
|
||||
<section>
|
||||
<title>Pre-Authentication Framework Classes</title>
|
||||
<para> Because most pre-authentication mechanisms follow the same pattern, Spring
|
||||
Security has a set of classes which provide an internal framework for implementing
|
||||
pre-authenticated authentication providers. This removes duplication and allows new
|
||||
implementations to be added in a structured fashion, without having to write everything from
|
||||
scratch. You don't need to know about these classes if you want to use something like
|
||||
<link xlink:href="#x509">X.509 authentication</link>, as it already has a namespace configuration
|
||||
option which is simpler to use and get started with. If you need to use explicit bean confiuration or
|
||||
are planning on writing your own implementation then an understanding of how the
|
||||
provided implementations work will be useful. You will find classes under the
|
||||
<package>org.springframework.security.web.authentication.preauth</package>. We just provide an outline
|
||||
here so you should consult the Javadoc and source where appropriate.
|
||||
</para>
|
||||
|
||||
<para> Because most pre-authentication mechanisms follow the same pattern, Spring Security has a
|
||||
set of classes which provide an internal framework for implementing pre-authenticated
|
||||
authentication providers. This removes duplication and allows new implementations to be added
|
||||
in a structured fashion, without having to write everything from scratch. You don't need to
|
||||
know about these classes if you want to use something like <link xlink:href="#x509">X.509
|
||||
authentication</link>, as it already has a namespace configuration option which is simpler
|
||||
to use and get started with. If you need to use explicit bean confiuration or are planning on
|
||||
writing your own implementation then an understanding of how the provided implementations work
|
||||
will be useful. You will find classes under the
|
||||
<package>org.springframework.security.web.authentication.preauth</package>. We just provide
|
||||
an outline here so you should consult the Javadoc and source where appropriate. </para>
|
||||
<section>
|
||||
<title>AbstractPreAuthenticatedProcessingFilter</title>
|
||||
<para>
|
||||
This class will check the current contents of the security context and, if empty, it will attempt to extract
|
||||
user information from the HTTP request and submit it to the <interfacename>AuthenticationManager</interfacename>.
|
||||
Subclasses override the following methods to obtain this information:
|
||||
<programlisting language="java">
|
||||
<para> This class will check the current contents of the security context and, if empty, it
|
||||
will attempt to extract user information from the HTTP request and submit it to the
|
||||
<interfacename>AuthenticationManager</interfacename>. Subclasses override the following
|
||||
methods to obtain this information:
|
||||
<programlisting language="java">
|
||||
protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request);
|
||||
|
||||
protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request);
|
||||
</programlisting>
|
||||
After calling these, the filter will create a <classname>PreAuthenticatedAuthenticationToken</classname>
|
||||
containing the returned data and submit it for authentication. By <quote>authentication</quote> here, we
|
||||
really just mean further processing to perhaps load the user's authorities, but the standard Spring Security
|
||||
authentication architecture is followed.
|
||||
</para>
|
||||
After calling these, the filter will create a
|
||||
<classname>PreAuthenticatedAuthenticationToken</classname> containing the returned data
|
||||
and submit it for authentication. By <quote>authentication</quote> here, we really just mean
|
||||
further processing to perhaps load the user's authorities, but the standard Spring Security
|
||||
authentication architecture is followed. </para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>AbstractPreAuthenticatedAuthenticationDetailsSource</title>
|
||||
<para>
|
||||
Like other Spring Security authentication filters, the pre-authentication filter has an
|
||||
<literal>authenticationDetailsSource</literal> property which by default will create a
|
||||
<classname>WebAuthenticationDetails</classname> object to store additional information such as
|
||||
the session-identifier and originating IP address in the <literal>details</literal> property of
|
||||
the <interfacename>Authentication</interfacename> object.
|
||||
In cases where user role information can be obtained from the pre-authentication mechanism, the
|
||||
data is also stored in this property. Subclasses of
|
||||
<classname>AbstractPreAuthenticatedAuthenticationDetailsSource</classname> use an extended details
|
||||
object which implements the <interfacename>GrantedAuthoritiesContainer</interfacename> interface, thus enabling the
|
||||
authentication provider to read the authorities which were externally allocated to the user. We'll look at a concrete
|
||||
example next.
|
||||
</para>
|
||||
<para> Like other Spring Security authentication filters, the pre-authentication filter has an
|
||||
<literal>authenticationDetailsSource</literal> property which by default will create a
|
||||
<classname>WebAuthenticationDetails</classname> object to store additional information
|
||||
such as the session-identifier and originating IP address in the <literal>details</literal>
|
||||
property of the <interfacename>Authentication</interfacename> object. In cases where user
|
||||
role information can be obtained from the pre-authentication mechanism, the data is also
|
||||
stored in this property. Subclasses of
|
||||
<classname>AbstractPreAuthenticatedAuthenticationDetailsSource</classname> use an extended
|
||||
details object which implements the
|
||||
<interfacename>GrantedAuthoritiesContainer</interfacename> interface, thus enabling the
|
||||
authentication provider to read the authorities which were externally allocated to the user.
|
||||
We'll look at a concrete example next. </para>
|
||||
<section xml:id="j2ee-preauth-details">
|
||||
<title>J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource</title>
|
||||
<para>
|
||||
If the filter is configured with an <literal>authenticationDetailsSource</literal> which is an instance of this
|
||||
class, the authority information is obtained by calling the <methodname>isUserInRole(String role)</methodname> method
|
||||
for each of a pre-determined set of <quote>mappable roles</quote>. The class gets these from a configured
|
||||
<interfacename>MappableAttributesRetriever</interfacename>. Possible implementations include hard-coding a list in the application
|
||||
context and reading the role information from the <literal><security-role></literal> information in a
|
||||
<filename>web.xml</filename> file. The pre-authentication sample application uses the latter approach.
|
||||
</para>
|
||||
<para>There is an additional stage where the roles (or attributes) are mapped to Spring Security
|
||||
<interfacename>GrantedAuthority</interfacename> objects using a configured
|
||||
<interfacename>Attributes2GrantedAuthoritiesMapper</interfacename>. The default will just add the usual <literal>ROLE_</literal>
|
||||
prefix to the names, but it gives you full control over the behaviour.
|
||||
</para>
|
||||
<para> If the filter is configured with an <literal>authenticationDetailsSource</literal>
|
||||
which is an instance of this class, the authority information is obtained by calling the
|
||||
<methodname>isUserInRole(String role)</methodname> method for each of a pre-determined
|
||||
set of <quote>mappable roles</quote>. The class gets these from a configured
|
||||
<interfacename>MappableAttributesRetriever</interfacename>. Possible implementations
|
||||
include hard-coding a list in the application context and reading the role information
|
||||
from the <literal><security-role></literal> information in a
|
||||
<filename>web.xml</filename> file. The pre-authentication sample application uses the
|
||||
latter approach. </para>
|
||||
<para>There is an additional stage where the roles (or attributes) are mapped to Spring
|
||||
Security <interfacename>GrantedAuthority</interfacename> objects using a configured
|
||||
<interfacename>Attributes2GrantedAuthoritiesMapper</interfacename>. The default will
|
||||
just add the usual <literal>ROLE_</literal> prefix to the names, but it gives you full
|
||||
control over the behaviour. </para>
|
||||
</section>
|
||||
</section>
|
||||
<section>
|
||||
<title>PreAuthenticatedAuthenticationProvider</title>
|
||||
<para>
|
||||
The pre-authenticated provider has little more to do than load the <interfacename>UserDetails</interfacename>
|
||||
object for the user. It does this by delegating to a <interfacename>AuthenticationUserDetailsService</interfacename>.
|
||||
The latter is similar to the standard <interfacename>UserDetailsService</interfacename> but takes an
|
||||
<interfacename>Authentication</interfacename> object rather than just user name:
|
||||
<programlisting language="java">
|
||||
<para> The pre-authenticated provider has little more to do than load the
|
||||
<interfacename>UserDetails</interfacename> object for the user. It does this by delegating
|
||||
to a <interfacename>AuthenticationUserDetailsService</interfacename>. The latter is similar
|
||||
to the standard <interfacename>UserDetailsService</interfacename> but takes an
|
||||
<interfacename>Authentication</interfacename> object rather than just user name:
|
||||
<programlisting language="java">
|
||||
public interface AuthenticationUserDetailsService {
|
||||
UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException;
|
||||
}
|
||||
</programlisting>
|
||||
This interface may have also other uses but with pre-authentication it allows access to the authorities which
|
||||
were packaged in the <interfacename>Authentication</interfacename> object, as we saw in the previous section.
|
||||
The <classname>PreAuthenticatedGrantedAuthoritiesUserDetailsService</classname> class does this.
|
||||
Alternatively, it may delegate to a standard <interfacename>UserDetailsService</interfacename> via the
|
||||
<classname>UserDetailsByNameServiceWrapper</classname> implementation.
|
||||
</para>
|
||||
</programlisting>
|
||||
This interface may have also other uses but with pre-authentication it allows access to the
|
||||
authorities which were packaged in the <interfacename>Authentication</interfacename> object,
|
||||
as we saw in the previous section. The
|
||||
<classname>PreAuthenticatedGrantedAuthoritiesUserDetailsService</classname> class does
|
||||
this. Alternatively, it may delegate to a standard
|
||||
<interfacename>UserDetailsService</interfacename> via the
|
||||
<classname>UserDetailsByNameServiceWrapper</classname> implementation. </para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Http403ForbiddenEntryPoint</title>
|
||||
<para>
|
||||
The <interfacename>AuthenticationEntryPoint</interfacename> was discussed in the <link xlink:href="#tech-intro-auth-entry-point">technical
|
||||
overview</link> chapter. Normally it is responsible for kick-starting the authentication process for an unauthenticated user
|
||||
(when they try to access a protected resource), but in the pre-authenticated case this doesn't apply. You would only
|
||||
configure the <classname>ExceptionTranslationFilter</classname> with an instance of this class if you aren't
|
||||
using pre-authentication in combination with other authentication mechanisms.
|
||||
It will be called if the user is rejected by the <classname>AbstractPreAuthenticatedProcessingFilter</classname>
|
||||
resulting in a null authentication. It always returns a <literal>403</literal>-forbidden response code if called.
|
||||
</para>
|
||||
<para> The <interfacename>AuthenticationEntryPoint</interfacename> was discussed in the <link
|
||||
xlink:href="#tech-intro-auth-entry-point">technical overview</link> chapter. Normally it
|
||||
is responsible for kick-starting the authentication process for an unauthenticated user
|
||||
(when they try to access a protected resource), but in the pre-authenticated case this
|
||||
doesn't apply. You would only configure the
|
||||
<classname>ExceptionTranslationFilter</classname> with an instance of this class if you
|
||||
aren't using pre-authentication in combination with other authentication mechanisms. It will
|
||||
be called if the user is rejected by the
|
||||
<classname>AbstractPreAuthenticatedProcessingFilter</classname> resulting in a null
|
||||
authentication. It always returns a <literal>403</literal>-forbidden response code if
|
||||
called. </para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Concrete Implementations</title>
|
||||
<para>
|
||||
X.509 authentication is covered in its <link xlink:href="#x509">own chapter</link>. Here we'll look at some classes
|
||||
which provide support for other pre-authenticated scenarios.
|
||||
</para>
|
||||
|
||||
<para> X.509 authentication is covered in its <link xlink:href="#x509">own chapter</link>. Here
|
||||
we'll look at some classes which provide support for other pre-authenticated scenarios. </para>
|
||||
<section>
|
||||
<title>Request-Header Authentication (Siteminder)</title>
|
||||
<para>
|
||||
An external authentication system may supply information to the application by setting specific headers on the HTTP request.
|
||||
A well known example of this is is Siteminder, which passes the username in a header called <literal>SM_USER</literal>.
|
||||
This mechanism is supported by the class <classname>RequestHeaderPreAuthenticatedProcessingFilter</classname> which
|
||||
simply extracts the username from the header. It defaults to using the name <literal>SM_USER</literal> as the
|
||||
header name. See the Javadoc for more details.
|
||||
</para>
|
||||
<para> An external authentication system may supply information to the application by setting
|
||||
specific headers on the HTTP request. A well known example of this is is Siteminder, which
|
||||
passes the username in a header called <literal>SM_USER</literal>. This mechanism is
|
||||
supported by the class <classname>RequestHeaderAuthenticationFilter</classname> which simply
|
||||
extracts the username from the header. It defaults to using the name
|
||||
<literal>SM_USER</literal> as the header name. See the Javadoc for more details. </para>
|
||||
<tip>
|
||||
<para>Note that when using a system like this, the framework performs no authentication checks at all and
|
||||
it is <emphasis>extremely</emphasis> important that the external system is configured properly and protects all
|
||||
access to the application. If an attacker is able to forge the headers in their original request without this being
|
||||
detected then they could potentially choose any userame they wished.
|
||||
</para>
|
||||
<para>Note that when using a system like this, the framework performs no authentication
|
||||
checks at all and it is <emphasis>extremely</emphasis> important that the external system
|
||||
is configured properly and protects all access to the application. If an attacker is able
|
||||
to forge the headers in their original request without this being detected then they could
|
||||
potentially choose any userame they wished. </para>
|
||||
</tip>
|
||||
<section>
|
||||
<title>Siteminder Example Configuration</title>
|
||||
<para>
|
||||
A typical configuration using this filter would look like this:
|
||||
<programlisting><![CDATA[
|
||||
<para> A typical configuration using this filter would look like this: <programlisting><![CDATA[
|
||||
<bean id="siteminderFilter" class=
|
||||
"org.springframework.security.web.authentication.preauth.header.RequestHeaderPreAuthenticatedProcessingFilter">
|
||||
"org.springframework.security.web.authentication.preauth.header.RequestHeaderAuthenticationFilter">
|
||||
<security:custom-filter position="PRE_AUTH_FILTER" />
|
||||
<property name="principalRequestHeader" value="SM_USER"/>
|
||||
<property name="authenticationManager" ref="authenticationManager" />
|
||||
|
@ -170,30 +157,27 @@ class="org.springframework.security.web.authentication.preauth.PreAuthenticatedA
|
|||
|
||||
<security:authentication-manager alias="authenticationManager" />
|
||||
]]>
|
||||
</programlisting>
|
||||
We've assumed here that the security namespace is being used for configuration (hence the user of the <literal>custom-filter</literal>,
|
||||
<literal>authentication-manager</literal> and <literal>custom-authentication-provider</literal> elements (you can read more about them
|
||||
in the <link xlink:href="ns-config">namespace chapter</link>). You would leave these out of a traditional bean configuration.
|
||||
It's also assumed that you have added a <interfacename>UserDetailsService</interfacename> (called <quote>userDetailsService</quote>)
|
||||
to your configuration to load the user's roles.
|
||||
</programlisting> We've assumed here that the security namespace is being used for
|
||||
configuration (hence the user of the <literal>custom-filter</literal>,
|
||||
<literal>authentication-manager</literal> and
|
||||
<literal>custom-authentication-provider</literal> elements (you can read more about them
|
||||
in the <link xlink:href="ns-config">namespace chapter</link>). You would leave these out
|
||||
of a traditional bean configuration. It's also assumed that you have added a
|
||||
<interfacename>UserDetailsService</interfacename> (called
|
||||
<quote>userDetailsService</quote>) to your configuration to load the user's roles.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>J2EE Container Authentication</title>
|
||||
<para>
|
||||
The class <classname>J2eePreAuthenticatedProcessingFilter</classname> will extract the username from the
|
||||
<literal>userPrincipal</literal> property of the <interfacename>HttpServletRequest</interfacename>. use of this
|
||||
filter would usually be combined with the use of J2EE roles as described above in <xref linkend="j2ee-preauth-details"/>.
|
||||
</para>
|
||||
<para>
|
||||
There is a sample application in the codebase which uses this approach, so get hold of the code from subversion and
|
||||
have a look at the application context file if you are interested. The code is in the <filename>samples/preauth</filename>
|
||||
directory.
|
||||
</para>
|
||||
|
||||
<para> The class <classname>J2eePreAuthenticatedProcessingFilter</classname> will extract the
|
||||
username from the <literal>userPrincipal</literal> property of the
|
||||
<interfacename>HttpServletRequest</interfacename>. use of this filter would usually be
|
||||
combined with the use of J2EE roles as described above in <xref
|
||||
linkend="j2ee-preauth-details"/>. </para>
|
||||
<para> There is a sample application in the codebase which uses this approach, so get hold of
|
||||
the code from subversion and have a look at the application context file if you are
|
||||
interested. The code is in the <filename>samples/preauth</filename> directory. </para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
</chapter>
|
||||
|
|
|
@ -1,34 +1,33 @@
|
|||
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="remember-me"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<info><title>Remember-Me Authentication</title></info>
|
||||
|
||||
|
||||
<section xml:id="remember-me-overview">
|
||||
<info><title>Overview</title></info>
|
||||
|
||||
<para>Remember-me or persistent-login authentication refers to web sites being able to
|
||||
remember the identity of a principal between sessions. This is
|
||||
typically accomplished by sending a cookie to the browser, with the
|
||||
cookie being detected during future sessions and causing automated
|
||||
login to take place. Spring Security provides the necessary hooks for
|
||||
these operations to take place, and has two concrete
|
||||
remember-me implementations. One uses hashing to preserve the security of
|
||||
cookie-based tokens and the other uses a database or other persistent storage
|
||||
mechanism to store the generated tokens. </para>
|
||||
<para>
|
||||
Note that both implemementations require a <interfacename>UserDetailsService</interfacename>.
|
||||
If you are using an authentication provider which doesn't use a <interfacename>UserDetailsService</interfacename>
|
||||
(for example, the LDAP provider) then it won't work unless you also have a <interfacename>UserDetailsService</interfacename>
|
||||
bean in your application context.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<info>
|
||||
<title>Remember-Me Authentication</title>
|
||||
</info>
|
||||
<section xml:id="remember-me-overview">
|
||||
<info>
|
||||
<title>Overview</title>
|
||||
</info>
|
||||
<para>Remember-me or persistent-login authentication refers to web sites being able to
|
||||
remember the identity of a principal between sessions. This is typically accomplished by
|
||||
sending a cookie to the browser, with the cookie being detected during future sessions
|
||||
and causing automated login to take place. Spring Security provides the necessary hooks
|
||||
for these operations to take place, and has two concrete remember-me implementations.
|
||||
One uses hashing to preserve the security of cookie-based tokens and the other uses a
|
||||
database or other persistent storage mechanism to store the generated tokens. </para>
|
||||
<para> Note that both implemementations require a
|
||||
<interfacename>UserDetailsService</interfacename>. If you are using an
|
||||
authentication provider which doesn't use a
|
||||
<interfacename>UserDetailsService</interfacename> (for example, the LDAP provider)
|
||||
then it won't work unless you also have a
|
||||
<interfacename>UserDetailsService</interfacename> bean in your application context.
|
||||
</para>
|
||||
</section>
|
||||
<section xml:id="remember-me-hash-token">
|
||||
<title>Simple Hash-Based Token Approach</title>
|
||||
<para>This approach uses hashing to achieve a useful remember-me strategy.
|
||||
In essence a cookie is sent to the browser upon successful interactive authentication, with the
|
||||
<para>This approach uses hashing to achieve a useful remember-me strategy. In essence a
|
||||
cookie is sent to the browser upon successful interactive authentication, with the
|
||||
cookie being composed as follows:
|
||||
<programlisting>
|
||||
<programlisting>
|
||||
base64(username + ":" + expirationTime + ":" +
|
||||
md5Hex(username + ":" + expirationTime + ":" password + ":" + key))
|
||||
|
||||
|
@ -38,109 +37,101 @@
|
|||
expressed in milliseconds
|
||||
key: A private key to prevent modification of the remember-me token
|
||||
</programlisting></para>
|
||||
<para>As such the remember-me token is valid only for the period
|
||||
specified, and provided that the username, password and key does not
|
||||
change. Notably, this has a potential security issue in that a
|
||||
captured remember-me token will be usable from any user agent until
|
||||
such time as the token expires. This is the same issue as with digest
|
||||
authentication. If a principal is aware a token has been captured,
|
||||
they can easily change their password and immediately invalidate all
|
||||
remember-me tokens on issue. If more significant security is
|
||||
needed you should use the approach described in the next section. Alternatively
|
||||
remember-me services should simply not be used at all.</para>
|
||||
|
||||
<para>If you are familiar with the topics discussed in the chapter on <link xlink:href="ns-config">namespace configuration</link>,
|
||||
you can enable remember-me authentication just by adding the <literal><remember-me></literal> element:
|
||||
<programlisting><![CDATA[
|
||||
<para>As such the remember-me token is valid only for the period specified, and provided
|
||||
that the username, password and key does not change. Notably, this has a potential
|
||||
security issue in that a captured remember-me token will be usable from any user agent
|
||||
until such time as the token expires. This is the same issue as with digest
|
||||
authentication. If a principal is aware a token has been captured, they can easily
|
||||
change their password and immediately invalidate all remember-me tokens on issue. If
|
||||
more significant security is needed you should use the approach described in the next
|
||||
section. Alternatively remember-me services should simply not be used at all.</para>
|
||||
<para>If you are familiar with the topics discussed in the chapter on <link
|
||||
xlink:href="ns-config">namespace configuration</link>, you can enable remember-me
|
||||
authentication just by adding the <literal><remember-me></literal> element: <programlisting><![CDATA[
|
||||
<http>
|
||||
...
|
||||
<remember-me key="myAppKey"/>
|
||||
</http>
|
||||
]]>
|
||||
</programlisting>
|
||||
The <interfacename>UserDetailsService</interfacename> will normally be selected automatically. If you have more than one in
|
||||
your application context, you need to specify which one should be used with the <literal>user-service-ref</literal> attribute,
|
||||
where the value is the name of your <interfacename>UserDetailsService</interfacename> bean.
|
||||
</para>
|
||||
</programlisting> The <interfacename>UserDetailsService</interfacename> will
|
||||
normally be selected automatically. If you have more than one in your application
|
||||
context, you need to specify which one should be used with the
|
||||
<literal>user-service-ref</literal> attribute, where the value is the name of your
|
||||
<interfacename>UserDetailsService</interfacename> bean. </para>
|
||||
</section>
|
||||
|
||||
<section xml:id="remember-me-persistent-token">
|
||||
<title>Persistent Token Approach</title>
|
||||
<para>This approach is based on the article
|
||||
<link xlink:href="http://jaspan.com/improved_persistent_login_cookie_best_practice">http://jaspan.com/improved_persistent_login_cookie_best_practice</link>
|
||||
with some minor modifications <footnote><para>Essentially, the username is not included in the cookie, to prevent exposing a valid login
|
||||
name unecessarily. There is a discussion on this in the comments section of this article.</para></footnote>.
|
||||
To use the this approach with namespace configuration, you would supply a datasource reference:
|
||||
<programlisting><![CDATA[
|
||||
<para>This approach is based on the article <link
|
||||
xlink:href="http://jaspan.com/improved_persistent_login_cookie_best_practice"
|
||||
>http://jaspan.com/improved_persistent_login_cookie_best_practice</link> with some
|
||||
minor modifications <footnote><para>Essentially, the username is not included in the
|
||||
cookie, to prevent exposing a valid login name unecessarily. There is a
|
||||
discussion on this in the comments section of this article.</para></footnote>.
|
||||
To use the this approach with namespace configuration, you would supply a datasource
|
||||
reference: <programlisting><![CDATA[
|
||||
<http>
|
||||
...
|
||||
<remember-me data-source-ref="someDataSource"/>
|
||||
</http>
|
||||
]]>
|
||||
</programlisting>
|
||||
The database should contain a <literal>persistent_logins</literal> table, created using the following SQL (or equivalent):
|
||||
<programlisting>
|
||||
</programlisting> The database should contain a
|
||||
<literal>persistent_logins</literal> table, created using the following SQL (or
|
||||
equivalent):
|
||||
<programlisting>
|
||||
create table persistent_logins (username varchar(64) not null, series varchar(64) primary key, token varchar(64) not null, last_used timestamp not null)
|
||||
</programlisting>
|
||||
</para>
|
||||
</programlisting></para>
|
||||
<!-- TODO: Add more info on the implementation and behaviour when tokens are stolen etc. Also some info for admins on invalidating tokens using key, or deleting info from db -->
|
||||
</section>
|
||||
|
||||
<section xml:id="remember-me-impls">
|
||||
<info><title>Remember-Me Interfaces and Implementations</title></info>
|
||||
|
||||
<para>Remember-me authentication is not used with basic
|
||||
authentication, given it is often not used with
|
||||
<literal>HttpSession</literal>s. Remember-me is used with
|
||||
<literal>UsernamePasswordAuthenticationFilter</literal>, and is implemented
|
||||
via hooks in the <literal>AbstractAuthenticationProcessingFilter</literal>
|
||||
superclass. The hooks will invoke a concrete
|
||||
<interfacename>RememberMeServices</interfacename> at the appropriate times. The
|
||||
interface looks like this:
|
||||
<programlisting language="java">
|
||||
</section>
|
||||
<section xml:id="remember-me-impls">
|
||||
<info>
|
||||
<title>Remember-Me Interfaces and Implementations</title>
|
||||
</info>
|
||||
<para>Remember-me authentication is not used with basic authentication, given it is often
|
||||
not used with <literal>HttpSession</literal>s. Remember-me is used with
|
||||
<literal>UsernamePasswordAuthenticationFilter</literal>, and is implemented via
|
||||
hooks in the <literal>AbstractAuthenticationProcessingFilter</literal> superclass. The
|
||||
hooks will invoke a concrete <interfacename>RememberMeServices</interfacename> at the
|
||||
appropriate times. The interface looks like this:
|
||||
<programlisting language="java">
|
||||
Authentication autoLogin(HttpServletRequest request, HttpServletResponse response);
|
||||
void loginFail(HttpServletRequest request, HttpServletResponse response);
|
||||
void loginSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication successfulAuthentication);
|
||||
</programlisting>
|
||||
Please refer to the JavaDocs for a fuller discussion on what the
|
||||
methods do, although note at this stage that
|
||||
<literal>AbstractAuthenticationProcessingFilter</literal> only calls the
|
||||
<literal>loginFail()</literal> and <literal>loginSuccess()</literal>
|
||||
methods. The <literal>autoLogin()</literal> method is called by
|
||||
<classname>RememberMeProcessingFilter</classname> whenever the
|
||||
<classname>SecurityContextHolder</classname> does not contain an
|
||||
<interfacename>Authentication</interfacename>. This interface therefore provides
|
||||
the underlying remember-me implementation with sufficient
|
||||
notification of authentication-related events, and delegates to the
|
||||
implementation whenever a candidate web request might contain a cookie
|
||||
and wish to be remembered. This design allows any number of remember-me implementation
|
||||
strategies. We've seen above that Spring Security provides
|
||||
two implementations. We'll look at thes in turn.</para>
|
||||
|
||||
Please refer to the JavaDocs for a fuller discussion on what the methods do, although
|
||||
note at this stage that <literal>AbstractAuthenticationProcessingFilter</literal> only
|
||||
calls the <literal>loginFail()</literal> and <literal>loginSuccess()</literal> methods.
|
||||
The <literal>autoLogin()</literal> method is called by
|
||||
<classname>RememberMeAuthenticationFilter</classname> whenever the
|
||||
<classname>SecurityContextHolder</classname> does not contain an
|
||||
<interfacename>Authentication</interfacename>. This interface therefore provides the
|
||||
underlying remember-me implementation with sufficient notification of
|
||||
authentication-related events, and delegates to the implementation whenever a candidate
|
||||
web request might contain a cookie and wish to be remembered. This design allows any
|
||||
number of remember-me implementation strategies. We've seen above that Spring Security
|
||||
provides two implementations. We'll look at thes in turn.</para>
|
||||
<section>
|
||||
<title>TokenBasedRememberMeServices</title>
|
||||
<para>
|
||||
This implementation supports the simpler approach described in <xref linkend="remember-me-hash-token"/>.
|
||||
<classname>TokenBasedRememberMeServices</classname> generates a
|
||||
<literal>RememberMeAuthenticationToken</literal>, which is processed
|
||||
by <literal>RememberMeAuthenticationProvider</literal>. A
|
||||
<literal>key</literal> is shared between this authentication provider
|
||||
and the <literal>TokenBasedRememberMeServices</literal>. In addition,
|
||||
<literal>TokenBasedRememberMeServices</literal> requires A
|
||||
UserDetailsService from which it can retrieve the username and
|
||||
password for signature comparison purposes, and generate the
|
||||
<literal>RememberMeAuthenticationToken</literal> to contain the
|
||||
correct <interfacename>GrantedAuthority</interfacename>[]s. Some sort of logout
|
||||
command should be provided by the application that invalidates the cookie if
|
||||
the user requests this. <classname>TokenBasedRememberMeServices</classname> also implements Spring Security's
|
||||
<interfacename>LogoutHandler</interfacename> interface so can be used with <classname>LogoutFilter</classname>
|
||||
to have the cookie cleared automatically.
|
||||
</para>
|
||||
<para>The beans required in an application context to enable remember-me services are as follows:
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<bean id="rememberMeProcessingFilter" class=
|
||||
"org.springframework.security.web.authentication.rememberme.RememberMeProcessingFilter">
|
||||
<para> This implementation supports the simpler approach described in <xref
|
||||
linkend="remember-me-hash-token"/>.
|
||||
<classname>TokenBasedRememberMeServices</classname> generates a
|
||||
<literal>RememberMeAuthenticationToken</literal>, which is processed by
|
||||
<literal>RememberMeAuthenticationProvider</literal>. A <literal>key</literal> is
|
||||
shared between this authentication provider and the
|
||||
<literal>TokenBasedRememberMeServices</literal>. In addition,
|
||||
<literal>TokenBasedRememberMeServices</literal> requires A UserDetailsService
|
||||
from which it can retrieve the username and password for signature comparison
|
||||
purposes, and generate the <literal>RememberMeAuthenticationToken</literal> to
|
||||
contain the correct <interfacename>GrantedAuthority</interfacename>[]s. Some sort of
|
||||
logout command should be provided by the application that invalidates the cookie if
|
||||
the user requests this. <classname>TokenBasedRememberMeServices</classname> also
|
||||
implements Spring Security's <interfacename>LogoutHandler</interfacename> interface
|
||||
so can be used with <classname>LogoutFilter</classname> to have the cookie cleared
|
||||
automatically. </para>
|
||||
<para>The beans required in an application context to enable remember-me services are as
|
||||
follows: <programlisting language="xml"><![CDATA[
|
||||
<bean id="rememberMeFilter" class=
|
||||
"org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
|
||||
<property name="rememberMeServices" ref="rememberMeServices"/>
|
||||
<property name="authenticationManager" ref="theAuthenticationManager" />
|
||||
</bean>
|
||||
|
@ -157,27 +148,26 @@
|
|||
</bean>
|
||||
]]>
|
||||
</programlisting>Don't forget to add your
|
||||
<interfacename>RememberMeServices</interfacename> implementation to your
|
||||
<literal>UsernamePasswordAuthenticationFilter.setRememberMeServices()</literal>
|
||||
property, include the
|
||||
<literal>RememberMeAuthenticationProvider</literal> in your
|
||||
<literal>AuthenticationManager.setProviders()</literal> list, and add
|
||||
<classname>RememberMeProcessingFilter</classname> into your
|
||||
<classname>FilterChainProxy</classname> (typically immediately after your
|
||||
<literal>UsernamePasswordAuthenticationFilter</literal>).</para>
|
||||
<interfacename>RememberMeServices</interfacename> implementation to your
|
||||
<literal>UsernamePasswordAuthenticationFilter.setRememberMeServices()</literal>
|
||||
property, include the <literal>RememberMeAuthenticationProvider</literal> in your
|
||||
<literal>AuthenticationManager.setProviders()</literal> list, and add
|
||||
<classname>RememberMeAuthenticationFilter</classname> into your
|
||||
<classname>FilterChainProxy</classname> (typically immediately after your
|
||||
<literal>UsernamePasswordAuthenticationFilter</literal>).</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>PersistentTokenBasedRememberMeServices</title>
|
||||
<para>
|
||||
This class can be used in the same way as <classname>TokenBasedRememberMeServices</classname>, but it additionally
|
||||
needs to be configured with a <interfacename>PersistentTokenRepository</interfacename> to store the tokens.
|
||||
There are two standard implementations.
|
||||
<itemizedlist>
|
||||
<listitem><para><classname>InMemoryTokenRepositoryImpl</classname> which is intended for testing only.</para></listitem>
|
||||
<listitem><para><classname>JdbcTokenRepositoryImpl</classname> which stores the tokens in a database. </para></listitem>
|
||||
</itemizedlist>
|
||||
The database schema is described above in <xref linkend="remember-me-persistent-token"/>.
|
||||
</para>
|
||||
<para> This class can be used in the same way as
|
||||
<classname>TokenBasedRememberMeServices</classname>, but it additionally needs
|
||||
to be configured with a <interfacename>PersistentTokenRepository</interfacename> to
|
||||
store the tokens. There are two standard implementations.
|
||||
<itemizedlist><listitem><para><classname>InMemoryTokenRepositoryImpl</classname>
|
||||
which is intended for testing
|
||||
only.</para></listitem><listitem><para><classname>JdbcTokenRepositoryImpl</classname>
|
||||
which stores the tokens in a database. </para></listitem></itemizedlist>
|
||||
The database schema is described above in <xref
|
||||
linkend="remember-me-persistent-token"/>. </para>
|
||||
</section>
|
||||
</section>
|
||||
</chapter>
|
||||
</chapter>
|
||||
|
|
|
@ -6,27 +6,27 @@
|
|||
<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>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>
|
||||
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
|
||||
Security, the filter classes are also Spring beans defined in the application context and thus
|
||||
able to take advantage of Spring's rich dependency-injection facilities and lifecycle
|
||||
interfaces. Spring's <classname>DelegatingFilterProxy</classname> provides the link between
|
||||
<filename>web.xml</filename> and the application context. </para>
|
||||
<para>When using <classname>DelegatingFilterProxy</classname>, you will see something like
|
||||
this in the <filename>web.xml</filename> file: <programlisting><![CDATA[
|
||||
<para>When using <classname>DelegatingFilterProxy</classname>, you will see something like this
|
||||
in the <filename>web.xml</filename> file: <programlisting><![CDATA[
|
||||
<filter>
|
||||
<filter-name>myFilter</filter-name>
|
||||
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
|
||||
|
@ -37,11 +37,11 @@
|
|||
<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
|
||||
<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>
|
||||
|
@ -50,11 +50,11 @@
|
|||
<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
|
||||
<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
|
||||
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
|
||||
|
@ -64,24 +64,24 @@
|
|||
<sec:filter-chain-map path-type="ant">
|
||||
<sec:filter-chain pattern="/webServices/**" filters="
|
||||
securityContextPersistenceFilterWithASCFalse,
|
||||
basicProcessingFilter,
|
||||
basicAuthenticationFilter,
|
||||
exceptionTranslationFilter,
|
||||
filterSecurityInterceptor" />
|
||||
<sec:filter-chain pattern="/**" filters="
|
||||
securityContextPersistenceFilterWithASCTrue,
|
||||
authenticationProcessingFilter,
|
||||
formLoginFilter,
|
||||
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
|
||||
</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
|
||||
|
@ -89,112 +89,92 @@
|
|||
URL.</para>
|
||||
<para>You may have noticed we have declared two
|
||||
<classname>SecurityContextPersistenceFilter</classname>s in the filter chain
|
||||
(<literal>ASC</literal> is short for <literal>allowSessionCreation</literal>, a property
|
||||
of <classname>SecurityContextPersistenceFilter</classname>). As web services will never
|
||||
present a <literal>jsessionid</literal> on future requests, creating
|
||||
<literal>HttpSession</literal>s for such user agents would be wasteful. If you had a
|
||||
high-volume application which required maximum scalability, we recommend you use the
|
||||
approach shown above. For smaller applications, using a single
|
||||
<classname>SecurityContextPersistenceFilter</classname> (with its default
|
||||
(<literal>ASC</literal> is short for <literal>allowSessionCreation</literal>, a property of
|
||||
<classname>SecurityContextPersistenceFilter</classname>). As web services will never present
|
||||
a <literal>jsessionid</literal> on future requests, creating <literal>HttpSession</literal>s
|
||||
for such user agents would be wasteful. If you had a high-volume application which required
|
||||
maximum scalability, we recommend you use the approach shown above. For smaller applications,
|
||||
using a single <classname>SecurityContextPersistenceFilter</classname> (with its default
|
||||
<literal>allowSessionCreation</literal> as <literal>true</literal>) would likely be
|
||||
sufficient.</para>
|
||||
<para>In relation to lifecycle issues, the <classname>FilterChainProxy</classname> will always
|
||||
delegate <methodname>init(FilterConfig)</methodname> and <methodname>destroy()</methodname>
|
||||
methods through to the underlaying <interfacename>Filter</interfacename>s if such methods
|
||||
are called against <classname>FilterChainProxy</classname> itself. In this case,
|
||||
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
|
||||
chain(s). You control the overall choice as to whether these methods are called or not via the
|
||||
<literal>targetFilterLifecycle</literal> initialization parameter of
|
||||
<literal>DelegatingFilterProxy</literal>. By default this property is
|
||||
<literal>false</literal> and servlet container lifecycle invocations are not delegated
|
||||
through <literal>DelegatingFilterProxy</literal>.</para>
|
||||
<para> When we looked at how to set up web security using <link
|
||||
xlink:href="#ns-web-xml">namespace configuration</link>, we used a
|
||||
<literal>DelegatingFilterProxy</literal> with the name
|
||||
<quote>springSecurityFilterChain</quote>. You should now be able to see that this is the
|
||||
<para> When we looked at how to set up web security using <link xlink:href="#ns-web-xml"
|
||||
>namespace configuration</link>, we used a <literal>DelegatingFilterProxy</literal> with the
|
||||
name <quote>springSecurityFilterChain</quote>. You should now be able to see that this is the
|
||||
name of the <classname>FilterChainProxy</classname> which is created by the namespace. </para>
|
||||
<section>
|
||||
<title>Bypassing the Filter Chain</title>
|
||||
<para> As with the namespace, you can use the attribute <literal>filters = "none"</literal>
|
||||
as an alternative to supplying a filter bean list. This will omit the request pattern from
|
||||
the security filter chain entirely. Note that anything matching this path will then have
|
||||
no authentication or authorization services applied and will be freely accessible. If you
|
||||
want to make use of the contents of the <classname>SecurityContext</classname> contents
|
||||
during a request, then it must have passed through the security filter chain. Otherwise
|
||||
the <classname>SecurityContextHolder</classname> will not have been populated and the
|
||||
contents will be null.</para>
|
||||
<para> As with the namespace, you can use the attribute <literal>filters = "none"</literal> as
|
||||
an alternative to supplying a filter bean list. This will omit the request pattern from the
|
||||
security filter chain entirely. Note that anything matching this path will then have no
|
||||
authentication or authorization services applied and will be freely accessible. If you want
|
||||
to make use of the contents of the <classname>SecurityContext</classname> contents during a
|
||||
request, then it must have passed through the security filter chain. Otherwise the
|
||||
<classname>SecurityContextHolder</classname> will not have been populated and the contents
|
||||
will be null.</para>
|
||||
</section>
|
||||
</section>
|
||||
<section>
|
||||
<title>Filter Ordering</title>
|
||||
<para>The order that filters are defined in the chain is very important. Irrespective of which
|
||||
filters you are actually using, the order should be as follows:
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
<para><classname>ChannelProcessingFilter</classname>, because it might need to redirect
|
||||
to a different protocol</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><classname>ConcurrentSessionFilter</classname>, because it doesn't use any
|
||||
<classname>SecurityContextHolder</classname> functionality but needs to update the
|
||||
<interfacename>SessionRegistry</interfacename> to reflect ongoing requests from the
|
||||
principal</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><classname>SecurityContextPersistenceFilter</classname>, so a
|
||||
<interfacename>SecurityContext</interfacename> can be set up in the
|
||||
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 -
|
||||
<literal>HttpSession</literal> when the web request ends (ready for use with the next
|
||||
web request)</para></listitem><listitem><para>Authentication processing mechanisms -
|
||||
<classname>UsernamePasswordAuthenticationFilter</classname>,
|
||||
<classname>CasProcessingFilter</classname>,
|
||||
<classname>BasicProcessingFilter</classname> etc - so that the
|
||||
<classname>CasAuthenticationFilter</classname>,
|
||||
<classname>BasicAuthenticationFilter</classname> etc - so that the
|
||||
<classname>SecurityContextHolder</classname> can be modified to contain a valid
|
||||
<interfacename>Authentication</interfacename> request token</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>The <literal>SecurityContextHolderAwareRequestFilter</literal>, if you are using
|
||||
it to install a Spring Security aware <literal>HttpServletRequestWrapper</literal>
|
||||
into your servlet container</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><classname>RememberMeProcessingFilter</classname>, so that if no earlier
|
||||
authentication processing mechanism updated the
|
||||
<interfacename>Authentication</interfacename> request
|
||||
token</para></listitem><listitem><para>The
|
||||
<literal>SecurityContextHolderAwareRequestFilter</literal>, if you are using it to
|
||||
install a Spring Security aware <literal>HttpServletRequestWrapper</literal> into your
|
||||
servlet
|
||||
container</para></listitem><listitem><para><classname>RememberMeAuthenticationFilter</classname>,
|
||||
so that if no earlier authentication processing mechanism updated the
|
||||
<classname>SecurityContextHolder</classname>, and the request presents a cookie that
|
||||
enables remember-me services to take place, a suitable remembered
|
||||
<interfacename>Authentication</interfacename> object will be put there</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><classname>AnonymousProcessingFilter</classname>, so that if no earlier
|
||||
authentication processing mechanism updated the
|
||||
<interfacename>Authentication</interfacename> object will be put
|
||||
there</para></listitem><listitem><para><classname>AnonymousAuthenticationFilter</classname>,
|
||||
so that if no earlier authentication processing mechanism updated the
|
||||
<classname>SecurityContextHolder</classname>, an anonymous
|
||||
<interfacename>Authentication</interfacename> object will be put there</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><classname>ExceptionTranslationFilter</classname>, to catch any Spring Security
|
||||
exceptions so that either an HTTP error response can be returned or an appropriate
|
||||
<interfacename>AuthenticationEntryPoint</interfacename> can be launched</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><classname>FilterSecurityInterceptor</classname>, to protect web URIs and raise
|
||||
exceptions when access is denied</para>
|
||||
</listitem>
|
||||
</orderedlist></para>
|
||||
<interfacename>Authentication</interfacename> object will be put
|
||||
there</para></listitem><listitem><para><classname>ExceptionTranslationFilter</classname>,
|
||||
to catch any Spring Security exceptions so that either an HTTP error response can be
|
||||
returned or an appropriate <interfacename>AuthenticationEntryPoint</interfacename> can
|
||||
be
|
||||
launched</para></listitem><listitem><para><classname>FilterSecurityInterceptor</classname>,
|
||||
to protect web URIs and raise exceptions when access is
|
||||
denied</para></listitem></orderedlist></para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Use with other Filter-Based Frameworks</title>
|
||||
<para>If you're using some other framework that is also filter-based, then you need to make
|
||||
sure that the Spring Security filters come first. This enables the
|
||||
<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>
|
||||
|
|
|
@ -35,11 +35,11 @@
|
|||
<para>
|
||||
<interfacename>SessionAuthenticationStrategy</interfacename> is used by both
|
||||
<classname>SessionManagementFilter</classname> and
|
||||
<classname>AbstractAutheticationProcessingFilter</classname>, so if you are using a
|
||||
<classname>AbstractAuthenticationProcessingFilter</classname>, so if you are using a
|
||||
customized form-login class, for example, you will need to inject it into both of these. In
|
||||
this case, a typical configuration, combining the namespace and custom beans might look like this:<programlisting><![CDATA[
|
||||
<http>
|
||||
<custom-filter position="AUTHENTICATION_PROCESSING_FILTER" ref="myAuthFilter" />
|
||||
<custom-filter position="FORM_LOGIN_FILTER" ref="myAuthFilter" />
|
||||
<session-management session-authentication-strategy-ref="sas"/>
|
||||
</http>
|
||||
|
||||
|
|
Loading…
Reference in New Issue