SEC-1178: More ref manual updates
This commit is contained in:
parent
ff5b90ef9d
commit
65d83faef2
|
@ -117,10 +117,7 @@
|
|||
<section xml:id="nsa-access-denied-page">
|
||||
<title><literal>access-denied-page</literal></title>
|
||||
<para>
|
||||
Allows the access denied page to be set (the user will be redirected here if an
|
||||
<exceptionname>AccessDeniedException</exceptionname> is raised). Corresponds to the
|
||||
<literal>errorPage</literal> property set on the <classname>AccessDeniedHandlerImpl</classname> which is
|
||||
used by the <classname>ExceptionTranslationFilter</classname>.
|
||||
Deprecated in favour of the <literal>access-denied-handler</literal> child element.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
@ -145,6 +142,16 @@
|
|||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section xml:id="nsa-access-denied-handler">
|
||||
<title><literal>access-denied-handler</literal></title>
|
||||
<para>
|
||||
This element allows you to set the <literal>errorPage</literal> property for the default
|
||||
<interfacename>AccessDeniedHandler</interfacename> used by the <classname>ExceptionTranslationFilter</classname>,
|
||||
(using the <literal>error-page</literal> attribute, or to supply your own implementation using the <literal>ref</literal>
|
||||
attribute. See <link xlink:href="#access-denied-handler"/> for more information on the implementation details.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>The <literal><intercept-url></literal> Element</title>
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="basic">
|
||||
<info>
|
||||
<title>Basic and Digest Authentication</title>
|
||||
</info>
|
||||
<para>Basic and digest authentiation are alternative authentication mechanisms which are popular
|
||||
in web applications. Basic authentication is often used with stateless clients which pass
|
||||
their credentials on each request. It's quite common to use it in combination with form-based
|
||||
authentication where an application is used through both a browser-based user interface
|
||||
and as a web-service. However, basic authentication transmits the password as plain text so it
|
||||
should only really be used over an encrypted transport layer such as HTTPS.</para>
|
||||
<section xml:id="basic-processing-filter">
|
||||
<info>
|
||||
<title><classname>BasicProcessingFilter</classname></title>
|
||||
</info>
|
||||
<para><literal>BasicProcessingFilter</literal> is responsible for processing basic
|
||||
authentication credentials presented in HTTP headers. This can be used for
|
||||
authenticating calls made by Spring remoting protocols (such as Hessian and Burlap), as
|
||||
well as normal browser user agents (such as Firefox and Internet Explorer). The standard
|
||||
governing HTTP Basic Authentication is defined by RFC 1945, Section 11, and
|
||||
<literal>BasicProcessingFilter</literal> conforms with this RFC. Basic
|
||||
Authentication is an attractive approach to authentication, because it is very widely
|
||||
deployed in user agents and implementation is extremely simple (it's just a Base64
|
||||
encoding of the username:password, specified in an HTTP header).</para>
|
||||
<section xml:id="basic-config">
|
||||
<info>
|
||||
<title>Configuration</title>
|
||||
</info>
|
||||
<para>To implement HTTP Basic Authentication, you need to add a
|
||||
<literal>BasicProcessingFilter</literal> to your filter chain. The application
|
||||
context should contain <literal>BasicProcessingFilter</literal> and its
|
||||
required collaborator:</para>
|
||||
<para>
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<bean id="basicProcessingFilter"
|
||||
class="org.springframework.security.web.authentication.www.BasicProcessingFilter">
|
||||
<property name="authenticationManager" ref="authenticationManager"/>
|
||||
<property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
|
||||
</bean>
|
||||
|
||||
<bean id="authenticationEntryPoint"
|
||||
class="org.springframework.security.web.authentication.www.BasicProcessingFilterEntryPoint">
|
||||
<property name="realmName" value="Name Of Your Realm"/>
|
||||
</bean>]]>
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>The configured <interfacename>AuthenticationManager</interfacename> processes each
|
||||
authentication request. If authentication fails, the configured
|
||||
<interfacename>AuthenticationEntryPoint</interfacename> will be used to retry the
|
||||
authentication process. Usually you will use the filter in combination with a
|
||||
<literal>BasicProcessingFilterEntryPoint</literal>, which returns a 401 response
|
||||
with a suitable header to retry HTTP Basic authentication. If authentication is
|
||||
successful, the resulting <interfacename>Authentication</interfacename> object will be
|
||||
placed into the <classname>SecurityContextHolder</classname> as usual.</para>
|
||||
<para>If the authentication event was successful, or authentication was not attempted
|
||||
because the HTTP header did not contain a supported authentication request, the filter
|
||||
chain will continue as normal. The only time the filter chain will be interrupted is if
|
||||
authentication fails and the <interfacename>AuthenticationEntryPoint</interfacename> is
|
||||
called.</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section xml:id="digest-processing-filter">
|
||||
<title><classname>DigestProcessingFilter</classname></title>
|
||||
<para><classname>DigestProcessingFilter</classname> is capable
|
||||
of processing digest authentication credentials presented in HTTP headers. Digest
|
||||
Authentication attempts to solve many of the weaknesses of Basic authentication,
|
||||
specifically by ensuring credentials are never sent in clear text across the wire. Many
|
||||
user agents support Digest Authentication, including FireFox and Internet Explorer. The
|
||||
standard governing HTTP Digest Authentication is defined by RFC 2617, which updates an
|
||||
earlier version of the Digest Authentication standard prescribed by RFC 2069. Most user
|
||||
agents implement RFC 2617. Spring Security's <classname>DigestProcessingFilter</classname> is
|
||||
compatible with the "<literal>auth</literal>" quality of protection
|
||||
(<literal>qop</literal>) prescribed by RFC 2617, which also provides backward
|
||||
compatibility with RFC 2069. Digest Authentication is a more attractive option if you
|
||||
need to use unencrypted HTTP (i.e. no TLS/HTTPS) and wish to maximise security of the
|
||||
authentication process. Indeed Digest Authentication is a mandatory requirement for the
|
||||
WebDAV protocol, as noted by RFC 2518 Section 17.1.</para>
|
||||
<para>Digest Authentication is definitely the most secure choice between Form
|
||||
Authentication, Basic Authentication and Digest Authentication, although extra security
|
||||
also means more complex user agent implementations. Central to Digest Authentication is
|
||||
a "nonce". This is a value the server generates. Spring Security's nonce adopts the
|
||||
following format:</para>
|
||||
<para>
|
||||
<programlisting>
|
||||
base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
|
||||
|
||||
expirationTime: The date and time when the nonce expires, expressed in milliseconds
|
||||
key: A private key to prevent modification of the nonce token
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>The <classname>DigestProcessingFilterEntryPoint</classname> has a property specifying the
|
||||
<literal>key</literal> used for generating the nonce tokens, along with a
|
||||
<literal>nonceValiditySeconds</literal> property for determining the expiration time
|
||||
(default 300, which equals five minutes). Whist ever the nonce is valid, the digest is
|
||||
computed by concatenating various strings including the username, password, nonce, URI
|
||||
being requested, a client-generated nonce (merely a random value which the user agent
|
||||
generates each request), the realm name etc, then performing an MD5 hash. Both the
|
||||
server and user agent perform this digest computation, resulting in different hash codes
|
||||
if they disagree on an included value (eg password). In Spring Security implementation,
|
||||
if the server-generated nonce has merely expired (but the digest was otherwise valid),
|
||||
the <classname>DigestProcessingFilterEntryPoint</classname> will send a
|
||||
<literal>"stale=true"</literal> header. This tells the user agent there is no need
|
||||
to disturb the user (as the password and username etc is correct), but simply to try
|
||||
again using a new nonce.</para>
|
||||
<para>An appropriate value for <classname>DigestProcessingFilterEntryPoint</classname>'s
|
||||
<literal>nonceValiditySeconds</literal> parameter will depend on your application.
|
||||
Extremely secure applications should note that an intercepted authentication header can
|
||||
be used to impersonate the principal until the <literal>expirationTime</literal>
|
||||
contained in the nonce is reached. This is the key principle when selecting an
|
||||
appropriate setting, but it would be unusual for immensely secure applications to not be
|
||||
running over TLS/HTTPS in the first instance.</para>
|
||||
<para>Because of the more complex implementation of Digest Authentication, there are often
|
||||
user agent issues. For example, Internet Explorer fails to present an
|
||||
"<literal>opaque</literal>" token on subsequent requests in the same session. Spring
|
||||
Security filters therefore encapsulate all state information into the
|
||||
"<literal>nonce</literal>" token instead. In our testing, Spring Security's
|
||||
implementation works reliably with FireFox and Internet Explorer, correctly handling
|
||||
nonce timeouts etc.</para>
|
||||
<section xml:id="digest-config">
|
||||
<title>Configuration</title>
|
||||
<para>Now that we've reviewed the theory, let's see how to use it. To implement HTTP Digest
|
||||
Authentication, it is necessary to define <literal>DigestProcessingFilter</literal> in
|
||||
the fitler chain. The application context will need to define the
|
||||
<literal>DigestProcessingFilter</literal> and its required collaborators:</para>
|
||||
<para>
|
||||
<programlisting><![CDATA[
|
||||
<bean id="digestProcessingFilter" class=
|
||||
"org.springframework.security.web.authentication.www.DigestProcessingFilter">
|
||||
<property name="userDetailsService" ref="jdbcDaoImpl"/>
|
||||
<property name="authenticationEntryPoint" ref="digestProcessingFilterEntryPoint"/>
|
||||
<property name="userCache" ref="userCache"/>
|
||||
</bean>
|
||||
|
||||
<bean id="digestProcessingFilterEntryPoint" class=
|
||||
"org.springframework.security.web.authentication.www.DigestProcessingFilterEntryPoint">
|
||||
<property name="realmName" value="Contacts Realm via Digest Authentication"/>
|
||||
<property name="key" value="acegi"/>
|
||||
<property name="nonceValiditySeconds" value="10"/>
|
||||
</bean>]]>
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>The configured <interfacename>UserDetailsService</interfacename> is needed because
|
||||
<literal>DigestProcessingFilter</literal> must have direct access to the clear text
|
||||
password of a user. Digest Authentication will NOT work if you are using encoded
|
||||
passwords in your DAO. The DAO collaborator, along with the
|
||||
<literal>UserCache</literal>, are typically shared directly with a
|
||||
<classname>DaoAuthenticationProvider</classname>. The
|
||||
<literal>authenticationEntryPoint</literal> property must be
|
||||
<classname>DigestProcessingFilterEntryPoint</classname>, so that
|
||||
<classname>DigestProcessingFilter</classname> can obtain the correct
|
||||
<literal>realmName</literal> and <literal>key</literal> for digest
|
||||
calculations.</para>
|
||||
<para>Like <literal>BasicAuthenticationFilter</literal>, if authentication is successful an
|
||||
<interfacename>Authentication</interfacename> request token will be placed into the
|
||||
<classname>SecurityContextHolder</classname>. If the authentication event was
|
||||
successful, or authentication was not attempted because the HTTP header did not contain
|
||||
a Digest Authentication request, the filter chain will continue as normal. The only time
|
||||
the filter chain will be interrupted is if authentication fails and the
|
||||
<interfacename>AuthenticationEntryPoint</interfacename> is called, as discussed in
|
||||
the previous paragraph.</para>
|
||||
<para>Digest Authentication's RFC offers a range of additional features to further increase
|
||||
security. For example, the nonce can be changed on every request. Despite this, Spring
|
||||
Security implementation was designed to minimise the complexity of the implementation
|
||||
(and the doubtless user agent incompatibilities that would emerge), and avoid needing to
|
||||
store server-side state. You are invited to review RFC 2617 if you wish to explore these
|
||||
features in more detail. As far as we are aware, Spring Security's implementation does
|
||||
comply with the minimum standards of this RFC.</para>
|
||||
</section>
|
||||
</section>
|
||||
</chapter>
|
|
@ -1,60 +0,0 @@
|
|||
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="basic"><info><title>BASIC Authentication Mechanism</title></info>
|
||||
|
||||
|
||||
<section xml:id="basic-overview"><info><title>Overview</title></info>
|
||||
|
||||
|
||||
<para>Spring Security provides a
|
||||
<literal>BasicProcessingFilter</literal> which is capable of
|
||||
processing basic authentication credentials presented in HTTP headers.
|
||||
This can be used for authenticating calls made by Spring remoting
|
||||
protocols (such as Hessian and Burlap), as well as normal user agents
|
||||
(such as Internet Explorer and Navigator). The standard governing HTTP
|
||||
Basic Authentication is defined by RFC 1945, Section 11, and the
|
||||
<literal>BasicProcessingFilter</literal> conforms with this RFC. Basic
|
||||
Authentication is an attractive approach to authentication, because it
|
||||
is very widely deployed in user agents and implementation is extremely
|
||||
simple (it's just a Base64 encoding of the username:password,
|
||||
specified in an HTTP header).</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="basic-config"><info><title>Configuration</title></info>
|
||||
|
||||
|
||||
<para>To implement HTTP Basic Authentication, it is necessary to
|
||||
define <literal>BasicProcessingFilter</literal> in the filter chain.
|
||||
The application context will need to define the
|
||||
<literal>BasicProcessingFilter</literal> and its required
|
||||
collaborator:</para>
|
||||
|
||||
<para><programlisting language="xml"><![CDATA[
|
||||
<bean id="basicProcessingFilter"
|
||||
class="org.springframework.security.web.authentication.www.BasicProcessingFilter">
|
||||
<property name="authenticationManager" ref="authenticationManager"/>
|
||||
<property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
|
||||
</bean>
|
||||
|
||||
<bean id="authenticationEntryPoint"
|
||||
class="org.springframework.security.web.authentication.www.BasicProcessingFilterEntryPoint">
|
||||
<property name="realmName" value="Name Of Your Realm"/>
|
||||
</bean>]]>
|
||||
</programlisting></para>
|
||||
|
||||
<para>The configured <interfacename>AuthenticationManager</interfacename>
|
||||
processes each authentication request. If authentication fails, the
|
||||
configured <interfacename>AuthenticationEntryPoint</interfacename> will be used to
|
||||
retry the authentication process. Usually you will use the
|
||||
<literal>BasicProcessingFilterEntryPoint</literal>, which returns a
|
||||
401 response with a suitable header to retry HTTP Basic
|
||||
authentication. If authentication is successful, the resulting
|
||||
<interfacename>Authentication</interfacename> object will be placed into the
|
||||
<classname>SecurityContextHolder</classname>.</para>
|
||||
|
||||
<para>If the authentication event was successful, or authentication
|
||||
was not attempted because the HTTP header did not contain a supported
|
||||
authentication request, the filter chain will continue as normal. The
|
||||
only time the filter chain will be interrupted is if authentication
|
||||
fails and the <interfacename>AuthenticationEntryPoint</interfacename> is called,
|
||||
as discussed in the previous paragraph</para>
|
||||
</section>
|
||||
</chapter>
|
|
@ -1,347 +0,0 @@
|
|||
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0"
|
||||
xml:id="authentication-common-auth-services" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<info>
|
||||
<title>Common Authentication Services</title>
|
||||
</info>
|
||||
<section xml:id="mechanisms-providers-entry-points">
|
||||
<info>
|
||||
<title>Mechanisms, Providers and Entry Points</title>
|
||||
</info>
|
||||
<para>To use Spring Security's authentication services, you'll usually need to configure a web
|
||||
filter, together with an <classname>AuthenticationProvider</classname> and
|
||||
<interfacename>AuthenticationEntryPoint</interfacename>. In this section we are going to
|
||||
explore an example application that needs to support both form-based authentication (so a nice
|
||||
HTML page is presented to a user for them to login) and BASIC authentication (so a web service
|
||||
or similar can access protected resources).</para>
|
||||
<para>The <literal>filter-chain-map</literal> syntax from the security namespace allows you to
|
||||
define the mapping from URLs to filter chains, using a sequence of
|
||||
<literal>filter-chain</literal> child elements. Each of these defines a set of URLs using
|
||||
the <literal>pattern</literal> attribute and a chain of filters using the
|
||||
<literal>filters</literal> attribute.What's important to note at this stage is that a series
|
||||
of filters will be run - in the order specified by the declaration - and each of those filters
|
||||
are actually the <literal>id</literal> of another bean in the application context. So, in our
|
||||
case some extra beans will also appear in the application context, and they'll be named
|
||||
<literal>httpSessionContextIntegrationFilter</literal>, <literal>logoutFilter</literal> and
|
||||
so on. The order that the filters should appear is discussed in the filters section of the
|
||||
reference guide - although they are correct in the above example.</para>
|
||||
<para>In our example we have the
|
||||
<literal>UsernamePasswordAuthenticationProcessingFilter</literal> and
|
||||
<literal>BasicProcessingFilter</literal> being used. These are the "authentication
|
||||
mechanisms" that respond to form-based authentication and BASIC HTTP header-based
|
||||
authentication respectively (we discussed the role of authentication mechanisms earlier in
|
||||
this reference guide). If you weren't using form or BASIC authentication, neither of these
|
||||
beans would be defined. You'd instead define filters applicable to your desired authentication
|
||||
environment, such as <literal>DigestProcessingFilter</literal> or
|
||||
<literal>CasProcessingFilter</literal>. Refer to the individual chapters of this part of the
|
||||
reference guide to learn how to configure each of these authentication mechanisms.</para>
|
||||
<para>Recall that <classname>HttpSessionContextIntegrationFilter</classname> keeps the contents
|
||||
of the <interfacename>SecurityContext</interfacename> between invocations inside an HTTP
|
||||
session. This means the authentication mechanisms are only used once, being when the principal
|
||||
initially tries to authenticate. The rest of the time the authentication mechanisms sit there
|
||||
and silently pass the request through to the next filter in the chain. That is a practical
|
||||
requirement due to the fact that few authentication approaches present credentials on each and
|
||||
every call (BASIC authentication being a notable exception), but what happens if a principal's
|
||||
account gets cancelled or disabled or otherwise changed (eg an increase or decrease in
|
||||
<literal>GrantedAuthority[]</literal>s) after the initial authentication step? Let's look at
|
||||
how that is handled now.</para>
|
||||
<para>The major authorization provider for secure objects has previously been introduced as
|
||||
<classname>AbstractSecurityInterceptor</classname>. This class needs to have access to an
|
||||
<interfacename>AuthenticationManager</interfacename>. It also has configurable settings to
|
||||
indicate whether an <interfacename>Authentication</interfacename> object should be
|
||||
re-authenticated on each secure object invocation. By default it just accepts any
|
||||
<interfacename>Authentication</interfacename> inside the
|
||||
<classname>SecurityContextHolder</classname> is authenticated if
|
||||
<literal>Authentication.isAuthenticated()</literal> returns true. This is great for
|
||||
performance, but not ideal if you want to ensure up-to-the-moment authentication validity. For
|
||||
such cases you'll probably want to set the
|
||||
<literal>AbstractSecurityInterceptor.alwaysReauthenticate</literal> property to true.</para>
|
||||
<para>You might be asking yourself, "what's this
|
||||
<interfacename>AuthenticationManager</interfacename>?". We haven't explored it before, but
|
||||
we have discussed the concept of an <classname>AuthenticationProvider</classname>. Quite
|
||||
simply, an <interfacename>AuthenticationManager</interfacename> is responsible for passing
|
||||
requests through a chain of AuthenticationProviders. It's a little like the filter chain we
|
||||
discussed earlier, although there are some differences. There is only one
|
||||
<interfacename>AuthenticationManager</interfacename> implementation shipped with Spring
|
||||
Security, so let's look at how it's configured for the example we're using in this
|
||||
chapter:</para>
|
||||
<para>
|
||||
<programlisting><![CDATA[
|
||||
<bean id="authenticationManager"
|
||||
class="org.springframework.security.authentication.ProviderManager">
|
||||
<property name="providers">
|
||||
<list>
|
||||
<ref local="daoAuthenticationProvider"/>
|
||||
<ref local="anonymousAuthenticationProvider"/>
|
||||
<ref local="rememberMeAuthenticationProvider"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>]]></programlisting>
|
||||
</para>
|
||||
<para>It's probably worth mentioning at this point that your authentication mechanisms (which
|
||||
are usually filters) are also injected with a reference to the
|
||||
<interfacename>AuthenticationManager</interfacename>. So both
|
||||
<classname>AbstractSecurityInterceptor</classname> as well as the authentication mechanisms
|
||||
will use the above <literal>ProviderManager</literal> to poll a list of
|
||||
<classname>AuthenticationProvider</classname>s.</para>
|
||||
<para>In our example we have three providers. They are tried in the order shown (which is
|
||||
implied by the use of a <literal>List</literal> instead of a <literal>Set</literal>), with
|
||||
each provider able to attempt authentication, or skip authentication by simply returning
|
||||
<literal>null</literal>. If all implementations return null, the
|
||||
<literal>ProviderManager</literal> will throw a suitable exception. If you're interested in
|
||||
learning more about chaining providers, please refer to the <literal>ProviderManager</literal>
|
||||
JavaDocs.</para>
|
||||
<para>The providers to use will sometimes be interchangeable with the authentication mechanisms,
|
||||
whilst at other times they will depend on a specific authentication mechanism. For example,
|
||||
the <literal>DaoAuthenticationProvider</literal> just needs a string-based username and
|
||||
password. Various authentication mechanisms result in the collection of a string-based
|
||||
username and password, including (but not limited to) BASIC and form authentication. Equally,
|
||||
some authentication mechanisms create an authentication request object which can only be
|
||||
interpreted by a single type of <classname>AuthenticationProvider</classname>. An example of
|
||||
this one-to-one mapping would be JA-SIG CAS, which uses the notion of a service ticket which
|
||||
can therefore only be authenticated by <literal>CasAuthenticationProvider</literal>. A further
|
||||
example of a one-to-one mapping would be the LDAP authentication mechanism, which can only be
|
||||
processed an the <literal>LdapAuthenticationProvider</literal>. The specifics of such
|
||||
relationships are detailed in the JavaDocs for each class, plus the authentication
|
||||
approach-specific chapters of this reference guide. You need not be terribly concerned about
|
||||
this implementation detail, because if you forget to register a suitable provider, you'll
|
||||
simply receive a <literal>ProviderNotFoundException</literal> when an attempt to authenticate
|
||||
is made.</para>
|
||||
<para>After configuring the correct authentication mechanisms in the
|
||||
<classname>FilterChainProxy</classname>, and ensuring that a corresponding
|
||||
<classname>AuthenticationProvider</classname> is registered in the
|
||||
<literal>ProviderManager</literal>, your last step is to configure an
|
||||
<interfacename>AuthenticationEntryPoint</interfacename>. Recall that earlier we discussed
|
||||
the role of <classname>ExceptionTranslationFilter</classname>, which is used when HTTP-based
|
||||
requests should receive back an HTTP header or HTTP redirect in order to start authentication.
|
||||
Continuing on with our earlier example:</para>
|
||||
<para>
|
||||
<programlisting><![CDATA[
|
||||
<bean id="exceptionTranslationFilter"
|
||||
class="org.springframework.security.web.access.ExceptionTranslationFilter">
|
||||
<property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
|
||||
<property name="accessDeniedHandler">
|
||||
<bean class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
|
||||
<property name="errorPage" value="/accessDenied.jsp"/>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="authenticationEntryPoint"
|
||||
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
|
||||
<property name="loginFormUrl" value="/login.jsp"/>
|
||||
<property name="forceHttps" value="false"/>
|
||||
</bean>]]></programlisting>
|
||||
</para>
|
||||
<para>Notice that the <classname>ExceptionTranslationFilter</classname> requires two
|
||||
collaborators. The first, <literal>AccessDeniedHandlerImpl</literal>, uses a
|
||||
<literal>RequestDispatcher</literal> forward to display the specified access denied error
|
||||
page. We use a forward so that the <classname>SecurityContextHolder</classname> still contains
|
||||
details of the principal, which may be useful for display to the user (in old releases of
|
||||
Spring Security we relied upon the servlet container to handle a 403 error message, which
|
||||
lacked this useful contextual information). <literal>AccessDeniedHandlerImpl</literal> will
|
||||
also set the HTTP header to 403, which is the official error code to indicate access denied.
|
||||
In the case of the <literal>AuthentionEntryPoint</literal>, here we're setting what action we
|
||||
would like taken when an unauthenticated principal attempts to perform a protected operation.
|
||||
Because in our example we're going to be using form-based authentication, we specify
|
||||
<literal>AuthenticationProcessinFilterEntryPoint</literal> and the URL of the login page.
|
||||
Your application will usually only have one entry point, and most authentication approaches
|
||||
define their own specific <interfacename>AuthenticationEntryPoint</interfacename>. Details of
|
||||
which entry point to use for each authentication approach is discussed in the authentication
|
||||
approach-specific chapters of this reference guide.</para>
|
||||
</section>
|
||||
<section xml:id="userdetails-and-associated-types">
|
||||
<info>
|
||||
<title>UserDetails and Associated Types</title>
|
||||
</info>
|
||||
<para>As mentioned in the first part of the reference guide, most authentication providers take
|
||||
advantage of the <interfacename>UserDetails</interfacename> and
|
||||
<interfacename>UserDetailsService</interfacename> interfaces. The contract for this latter
|
||||
interface consists of a single method:</para>
|
||||
<para>
|
||||
<programlisting>
|
||||
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException;
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>The returned <interfacename>UserDetails</interfacename> is an interface that provides
|
||||
getters that guarantee non-null provision of basic authentication information such as the
|
||||
username, password, granted authorities and whether the user is enabled or disabled. Most
|
||||
authentication providers will use a <interfacename>UserDetailsService</interfacename>, even if
|
||||
the username and password are not actually used as part of the authentication decision.
|
||||
Generally such providers will be using the returned <interfacename>UserDetails</interfacename>
|
||||
object just for its <literal>GrantedAuthority[]</literal> information, because some other
|
||||
system (like LDAP or X509 or CAS etc) has undertaken the responsibility of actually validating
|
||||
the credentials.</para>
|
||||
<para>A single concrete implementation of <interfacename>UserDetails</interfacename> is provided
|
||||
with Spring Security, being the <literal>User</literal> class. Spring Security users will need
|
||||
to decide when writing their <interfacename>UserDetailsService</interfacename> what concrete
|
||||
<interfacename>UserDetails</interfacename> class to return. In most cases
|
||||
<literal>User</literal> will be used directly or subclassed, although special circumstances
|
||||
(such as object relational mappers) may require users to write their own
|
||||
<interfacename>UserDetails</interfacename> implementation from scratch. This is not such an
|
||||
unusual situation, and users should not hesitate to simply return their normal domain object
|
||||
that represents a user of the system. This is especially common given that
|
||||
<interfacename>UserDetails</interfacename> is often used to store additional
|
||||
principal-related properties (such as their telephone number and email address), so that they
|
||||
can be easily used by web views.</para>
|
||||
<para>Given <interfacename>UserDetailsService</interfacename> is so simple to implement, it
|
||||
should be easy for users to retrieve authentication information using a persistence strategy
|
||||
of their choice. Having said that, Spring Security does include a couple of useful base
|
||||
implementations, which we'll look at below.</para>
|
||||
<section xml:id="in-memory-service">
|
||||
<info>
|
||||
<title>In-Memory Authentication</title>
|
||||
</info>
|
||||
<para>Whilst it is easy to use create a custom
|
||||
<interfacename>UserDetailsService</interfacename> implementation that extracts information
|
||||
from a persistence engine of choice, many applications do not require such complexity. This
|
||||
is particularly true if you're undertaking a rapid prototype or just starting integrating
|
||||
Spring Security, when you don't really want to spend time configuring databases or writing
|
||||
<interfacename>UserDetailsService</interfacename> implementations. For this sort of
|
||||
situation, a simple option is to use the <literal>user-service</literal> element from the
|
||||
security <link xlink:href="#namespace-minimal">namespace</link>: <programlisting><![CDATA[
|
||||
<user-service id="userDetailsService">
|
||||
<user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
|
||||
<user name="bob" password="bobspassword" authorities="ROLE_USER" />
|
||||
</user-service>
|
||||
]]>
|
||||
</programlisting> This also suppots the use of an external properties file: <programlisting><![CDATA[
|
||||
<user-service id="userDetailsService" properties="users.properties"/>
|
||||
]]></programlisting> The properties file should contain entries in the form
|
||||
<programlisting>
|
||||
username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]
|
||||
</programlisting>
|
||||
For example
|
||||
<programlisting>
|
||||
jimi=jimispassword,ROLE_USER,ROLE_ADMIN,enabled
|
||||
bob=bobspassword,ROLE_USER,enabled
|
||||
</programlisting></para>
|
||||
</section>
|
||||
<section xml:id="jdbc-service">
|
||||
<info>
|
||||
<title>JDBC Authentication</title>
|
||||
</info>
|
||||
<para>Spring Security also includes a <interfacename>UserDetailsService</interfacename> that
|
||||
can obtain authentication information from a JDBC data source. Internally Spring JDBC is
|
||||
used, so it avoids the complexity of a fully-featured object relational mapper (ORM) just to
|
||||
store user details. If your application does use an ORM tool, you might prefer to write a
|
||||
custom <interfacename>UserDetailsService</interfacename> to reuse the mapping files you've
|
||||
probably already created. Returning to <literal>JdbcDaoImpl</literal>, an example
|
||||
configuration is shown below:</para>
|
||||
<para>
|
||||
<programlisting>
|
||||
<![CDATA[
|
||||
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
|
||||
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
|
||||
<property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/>
|
||||
<property name="username" value="sa"/>
|
||||
<property name="password" value=""/>
|
||||
</bean>
|
||||
|
||||
<bean id="userDetailsService" class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
|
||||
<property name="dataSource" ref="dataSource"/>
|
||||
</bean> ]]> </programlisting>
|
||||
</para>
|
||||
<para>You can use different relational database management systems by modifying the
|
||||
<literal>DriverManagerDataSource</literal> shown above. You can also use a global data
|
||||
source obtained from JNDI, as per normal Spring options. </para>
|
||||
<section xml:id="jdbc-default-schema">
|
||||
<title>Default User Database Schema</title>
|
||||
<para> Irrespective of the database you are using and how a <literal>DataSource</literal> is
|
||||
obtained, a standard schema must be in place. The DDL for an HSQL database instance would
|
||||
be:
|
||||
<programlisting>
|
||||
CREATE TABLE users (
|
||||
username VARCHAR(50) NOT NULL PRIMARY KEY,
|
||||
password VARCHAR(50) NOT NULL,
|
||||
enabled BIT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE authorities (
|
||||
username VARCHAR(50) NOT NULL,
|
||||
authority VARCHAR(50) NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE authorities ADD CONSTRAINT fk_authorities_users \
|
||||
foreign key (username) REFERENCES users(username);
|
||||
</programlisting></para>
|
||||
<para>If the default schema is unsuitable for your needs, <literal>JdbcDaoImpl</literal>
|
||||
provides properties that allow customisation of the SQL statements. Please refer to the
|
||||
JavaDocs for details, but note that the class is not intended for complex custom
|
||||
subclasses. If you have a complex schema or would like a custom
|
||||
<interfacename>UserDetails</interfacename> implementation returned, you'd be better off
|
||||
writing your own <interfacename>UserDetailsService</interfacename>. The base
|
||||
implementation provided with Spring Security is intended for typical situations, rather
|
||||
than catering for all possible requirements.</para>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
<section xml:id="concurrent-sessions">
|
||||
<info>
|
||||
<title>Concurrent Session Handling</title>
|
||||
</info>
|
||||
<para>Spring Security is able to prevent a principal from concurrently authenticating to the
|
||||
same application more than a specified number of times. Many ISVs take advantage of this to
|
||||
enforce licensing, whilst network administrators like this feature because it helps prevent
|
||||
people from sharing login names. You can, for example, stop user "Batman" from logging onto
|
||||
the web application from two different sessions.</para>
|
||||
<para>To use concurrent session support, you'll need to add the following to
|
||||
<literal>web.xml</literal>: <programlisting><![CDATA[
|
||||
<listener>
|
||||
<listener-class>
|
||||
org.springframework.security.web.session.HttpSessionEventPublisher
|
||||
</listener-class>
|
||||
</listener> ]]>
|
||||
</programlisting></para>
|
||||
<para>In addition, you will need to add the
|
||||
<literal>org.springframework.security.web.authentication.concurrent.ConcurrentSessionFilter</literal>
|
||||
to your <classname>FilterChainProxy</classname>. The
|
||||
<classname>ConcurrentSessionFilter</classname> requires two properties,
|
||||
<literal>sessionRegistry</literal>, which generally points to an instance of
|
||||
<literal>SessionRegistryImpl</literal>, and <literal>expiredUrl</literal>, which points to
|
||||
the page to display when a session has expired.</para>
|
||||
<para>The <literal>web.xml</literal>
|
||||
<literal>HttpSessionEventPublisher</literal> causes an <literal>ApplicationEvent</literal> to
|
||||
be published to the Spring <literal>ApplicationContext</literal> every time a
|
||||
<literal>HttpSession</literal> commences or terminates. This is critical, as it allows the
|
||||
<classname>SessionRegistryImpl</classname> to be notified when a session ends.</para>
|
||||
<para>You will also need to wire up the <classname>ConcurrentSessionControllerImpl</classname>
|
||||
and refer to it from your <literal>ProviderManager</literal> bean:</para>
|
||||
<para>
|
||||
<programlisting><![CDATA[
|
||||
<bean id="authenticationManager"
|
||||
class="org.springframework.security.authentication.ProviderManager">
|
||||
<property name="providers">
|
||||
<!-- your providers go here -->
|
||||
</property>
|
||||
<property name="sessionController" ref="concurrentSessionController"/>
|
||||
</bean>
|
||||
|
||||
<bean id="concurrentSessionController" class=
|
||||
"org.springframework.security.authentication.concurrent.ConcurrentSessionControllerImpl">
|
||||
<property name="maximumSessions" value="1"/>
|
||||
<property name="sessionRegistry">
|
||||
<bean
|
||||
class="org.springframework.security.authentication.concurrent.SessionRegistryImpl"/>
|
||||
<property>
|
||||
</bean>
|
||||
]]></programlisting>
|
||||
</para>
|
||||
</section>
|
||||
<section xml:id="authentication-taglibs">
|
||||
<info>
|
||||
<title>Authentication Tag Libraries</title>
|
||||
</info>
|
||||
<para><literal>AuthenticationTag</literal> is used to simply output a property of the current
|
||||
<interfacename>Authentication</interfacename> object to the web page.</para>
|
||||
<para>The following JSP fragment illustrates how to use the
|
||||
<literal>AuthenticationTag</literal>:</para>
|
||||
<para>
|
||||
<programlisting><security:authentication property="principal.username"/></programlisting>
|
||||
</para>
|
||||
<para>This tag would cause the principal's name to be output. Here we are assuming the
|
||||
<literal>Authentication.getPrincipal()</literal> is a
|
||||
<interfacename>UserDetails</interfacename> object, which is generally the case when using
|
||||
one of Spring Security's stadard <classname>AuthenticationProvider</classname>
|
||||
implementations.</para>
|
||||
</section>
|
||||
</chapter>
|
|
@ -1,144 +0,0 @@
|
|||
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="digest"><info><title>Digest Authentication</title></info>
|
||||
|
||||
|
||||
<section xml:id="digest-overview"><info><title>Overview</title></info>
|
||||
|
||||
|
||||
<para>Spring Security provides a
|
||||
<literal>DigestProcessingFilter</literal> which is capable of
|
||||
processing digest authentication credentials presented in HTTP
|
||||
headers. Digest Authentication attempts to solve many of the
|
||||
weaknesses of Basic authentication, specifically by ensuring
|
||||
credentials are never sent in clear text across the wire. Many user
|
||||
agents support Digest Authentication, including FireFox and Internet
|
||||
Explorer. The standard governing HTTP Digest Authentication is defined
|
||||
by RFC 2617, which updates an earlier version of the Digest
|
||||
Authentication standard prescribed by RFC 2069. Most user agents
|
||||
implement RFC 2617. Spring Security
|
||||
<literal>DigestProcessingFilter</literal> is compatible with the
|
||||
"<literal>auth</literal>" quality of protection
|
||||
(<literal>qop</literal>) prescribed by RFC 2617, which also provides
|
||||
backward compatibility with RFC 2069. Digest Authentication is a
|
||||
highly attractive option if you need to use unencrypted HTTP (ie no
|
||||
TLS/HTTPS) and wish to maximise security of the authentication
|
||||
process. Indeed Digest Authentication is a mandatory requirement for
|
||||
the WebDAV protocol, as noted by RFC 2518 Section 17.1, so we should
|
||||
expect to see it increasingly deployed and replacing Basic
|
||||
Authentication.</para>
|
||||
|
||||
<para>Digest Authentication is definitely the most secure choice
|
||||
between Form Authentication, Basic Authentication and Digest
|
||||
Authentication, although extra security also means more complex user
|
||||
agent implementations. Central to Digest Authentication is a "nonce".
|
||||
This is a value the server generates. Spring Security's nonce adopts
|
||||
the following format:</para>
|
||||
|
||||
<para><programlisting>
|
||||
base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
|
||||
|
||||
expirationTime: The date and time when the nonce expires, expressed in milliseconds
|
||||
key: A private key to prevent modification of the nonce token
|
||||
</programlisting></para>
|
||||
|
||||
<para>The <literal>DigestProcessingFilterEntryPoint</literal> has a
|
||||
property specifying the <literal>key</literal> used for generating the
|
||||
nonce tokens, along with a <literal>nonceValiditySeconds</literal>
|
||||
property for determining the expiration time (default 300, which
|
||||
equals five minutes). Whist ever the nonce is valid, the digest is
|
||||
computed by concatenating various strings including the username,
|
||||
password, nonce, URI being requested, a client-generated nonce (merely
|
||||
a random value which the user agent generates each request), the realm
|
||||
name etc, then performing an MD5 hash. Both the server and user agent
|
||||
perform this digest computation, resulting in different hash codes if
|
||||
they disagree on an included value (eg password). In Spring Security
|
||||
implementation, if the server-generated nonce has merely expired (but
|
||||
the digest was otherwise valid), the
|
||||
<literal>DigestProcessingFilterEntryPoint</literal> will send a
|
||||
<literal>"stale=true"</literal> header. This tells the user agent
|
||||
there is no need to disturb the user (as the password and username etc
|
||||
is correct), but simply to try again using a new nonce.</para>
|
||||
|
||||
<para>An appropriate value for
|
||||
<literal>DigestProcessingFilterEntryPoint</literal>'s
|
||||
<literal>nonceValiditySeconds</literal> parameter will depend on your
|
||||
application. Extremely secure applications should note that an
|
||||
intercepted authentication header can be used to impersonate the
|
||||
principal until the <literal>expirationTime</literal> contained in the
|
||||
nonce is reached. This is the key principle when selecting an
|
||||
appropriate setting, but it would be unusual for immensely secure
|
||||
applications to not be running over TLS/HTTPS in the first
|
||||
instance.</para>
|
||||
|
||||
<para>Because of the more complex implementation of Digest
|
||||
Authentication, there are often user agent issues. For example,
|
||||
Internet Explorer fails to present an "<literal>opaque</literal>"
|
||||
token on subsequent requests in the same session. Spring Security
|
||||
filters therefore encapsulate all state information into the
|
||||
"<literal>nonce</literal>" token instead. In our testing, Spring
|
||||
Security implementation works reliably with FireFox and Internet
|
||||
Explorer, correctly handling nonce timeouts etc.</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="digest-config"><info><title>Configuration</title></info>
|
||||
|
||||
|
||||
<para>Now that we've reviewed the theory, let's see how to use it. To
|
||||
implement HTTP Digest Authentication, it is necessary to define
|
||||
<literal>DigestProcessingFilter</literal> in the fitler chain. The
|
||||
application context will need to define the
|
||||
<literal>DigestProcessingFilter</literal> and its required
|
||||
collaborators:</para>
|
||||
|
||||
<para><programlisting>
|
||||
<![CDATA[
|
||||
<bean id="digestProcessingFilter" class=
|
||||
"org.springframework.security.web.authentication.www.DigestProcessingFilter">
|
||||
<property name="userDetailsService" ref="jdbcDaoImpl"/>
|
||||
<property name="authenticationEntryPoint" ref="digestProcessingFilterEntryPoint"/>
|
||||
<property name="userCache" ref="userCache"/>
|
||||
</bean>
|
||||
|
||||
<bean id="digestProcessingFilterEntryPoint" class=
|
||||
"org.springframework.security.web.authentication.www.DigestProcessingFilterEntryPoint">
|
||||
<property name="realmName" value="Contacts Realm via Digest Authentication"/>
|
||||
<property name="key" value="acegi"/>
|
||||
<property name="nonceValiditySeconds" value="10"/>
|
||||
</bean>]]>
|
||||
|
||||
</programlisting></para>
|
||||
|
||||
<para>The configured <interfacename>UserDetailsService</interfacename> is needed
|
||||
because <literal>DigestProcessingFilter</literal> must have direct
|
||||
access to the clear text password of a user. Digest Authentication
|
||||
will NOT work if you are using encoded passwords in your DAO. The DAO
|
||||
collaborator, along with the <literal>UserCache</literal>, are
|
||||
typically shared directly with a
|
||||
<literal>DaoAuthenticationProvider</literal>. The
|
||||
<literal>authenticationEntryPoint</literal> property must be
|
||||
<literal>DigestProcessingFilterEntryPoint</literal>, so that
|
||||
<literal>DigestProcessingFilter</literal> can obtain the correct
|
||||
<literal>realmName</literal> and <literal>key</literal> for digest
|
||||
calculations.</para>
|
||||
|
||||
<para>Like <literal>BasicAuthenticationFilter</literal>, if
|
||||
authentication is successful an <interfacename>Authentication</interfacename>
|
||||
request token will be placed into the
|
||||
<classname>SecurityContextHolder</classname>. If the authentication event
|
||||
was successful, or authentication was not attempted because the HTTP
|
||||
header did not contain a Digest Authentication request, the filter
|
||||
chain will continue as normal. The only time the filter chain will be
|
||||
interrupted is if authentication fails and the
|
||||
<interfacename>AuthenticationEntryPoint</interfacename> is called, as discussed in
|
||||
the previous paragraph.</para>
|
||||
|
||||
<para>Digest Authentication's RFC offers a range of additional
|
||||
features to further increase security. For example, the nonce can be
|
||||
changed on every request. Despite this, Spring Security implementation
|
||||
was designed to minimise the complexity of the implementation (and the
|
||||
doubtless user agent incompatibilities that would emerge), and avoid
|
||||
needing to store server-side state. You are invited to review RFC 2617
|
||||
if you wish to explore these features in more detail. As far as we are
|
||||
aware, Spring Security's implementation does comply with the minimum
|
||||
standards of this RFC.</para>
|
||||
</section>
|
||||
</chapter>
|
|
@ -63,7 +63,5 @@
|
|||
</note>
|
||||
If authentication fails, the configured <interfacename>AuthenticationFailureHandler</interfacename> will be invoked.
|
||||
</para>
|
||||
|
||||
|
||||
</section>
|
||||
</chapter>
|
|
@ -145,121 +145,4 @@ public void afterPropertiesSet() throws Exception {
|
|||
whatever means you think fit (eg <literal>new Person();</literal>) and they will have the
|
||||
security interceptor applied.</para>
|
||||
</section>
|
||||
<section xml:id="filter-invocation-authorization">
|
||||
<info>
|
||||
<title>FilterInvocation Security Interceptor</title>
|
||||
</info>
|
||||
<para>To secure <classname>FilterInvocation</classname>s, developers need to add a
|
||||
<classname>FilterSecurityInterceptor</classname> to their filter chain. A typical
|
||||
configuration example is provided below:</para>
|
||||
<para>In the application context you will need to configure three beans:</para>
|
||||
<programlisting>
|
||||
<![CDATA[
|
||||
<bean id="exceptionTranslationFilter"
|
||||
class="org.springframework.security.web.access.ExceptionTranslationFilter">
|
||||
<property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
|
||||
</bean>
|
||||
|
||||
<bean id="authenticationEntryPoint"
|
||||
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
|
||||
<property name="loginFormUrl" value="/acegilogin.jsp"/>
|
||||
<property name="forceHttps" value="false"/>
|
||||
</bean>
|
||||
|
||||
<bean id="filterSecurityInterceptor"
|
||||
class="org.springframework.security.intercept.web.FilterSecurityInterceptor">
|
||||
<property name="authenticationManager" ref="authenticationManager"/>
|
||||
<property name="accessDecisionManager" ref="accessDecisionManager"/>
|
||||
<property name="securityMetadataSource">
|
||||
<security:filter-security-metadata-source>
|
||||
<security:intercept-url pattern="/secure/super/**" access="ROLE_WE_DONT_HAVE"/>
|
||||
<security:intercept-url pattern="/secure/**" access="ROLE_SUPERVISOR,ROLE_TELLER"/>
|
||||
</security:filter-security-metadata-source>
|
||||
</property>
|
||||
</bean>]]> </programlisting>
|
||||
<para>The <classname>ExceptionTranslationFilter</classname> provides the bridge between Java
|
||||
exceptions and HTTP responses. It is solely concerned with maintaining the user interface.
|
||||
This filter does not do any actual security enforcement. If an
|
||||
<exceptionname>AuthenticationException</exceptionname> is detected, the filter will call the
|
||||
AuthenticationEntryPoint to commence the authentication process (e.g. a user login).</para>
|
||||
<para>The <interfacename>AuthenticationEntryPoint</interfacename> will be called if the user
|
||||
requests a secure HTTP resource but they are not authenticated. The class handles presenting
|
||||
the appropriate response to the user so that authentication can begin. Three concrete
|
||||
implementations are provided with Spring Security:
|
||||
<classname>LoginUrlAuthenticationEntryPoint</classname> for commencing a form-based
|
||||
authentication, <literal>BasicProcessingFilterEntryPoint</literal> for commencing a HTTP Basic
|
||||
authentication process, and <literal>CasProcessingFilterEntryPoint</literal> for commencing a
|
||||
JA-SIG Central Authentication Service (CAS) login. The
|
||||
<classname>LoginUrlAuthenticationEntryPoint</classname> and
|
||||
<literal>CasProcessingFilterEntryPoint</literal> have optional properties related to forcing
|
||||
the use of HTTPS, so please refer to the JavaDocs if you require this.</para>
|
||||
<para><classname>FilterSecurityInterceptor</classname> is responsible for handling the security
|
||||
of HTTP resources. Like any other security interceptor, it requires a reference to an
|
||||
<interfacename>AuthenticationManager</interfacename> and an
|
||||
<interfacename>AccessDecisionManager</interfacename>, which are both discussed in separate
|
||||
sections below. The <classname>FilterSecurityInterceptor</classname> is also configured with
|
||||
configuration attributes that apply to different HTTP URL requests. A full discussion of
|
||||
configuration attributes is provided in the High Level Design section of this document.</para>
|
||||
<para>The <classname>FilterSecurityInterceptor</classname> can be configured with configuration
|
||||
attributes in two ways. The first, which is shown above, is using the
|
||||
<literal><filter-security-metadata-source></literal> namespace element. This is
|
||||
similar to the <literal><filter-chain-map></literal> used to configure a
|
||||
<classname>FilterChainProxy</classname> but the <literal><intercept-url></literal>
|
||||
child elements only use the <literal>pattern</literal> and <literal>access</literal>
|
||||
attributes. The second is by writing your own
|
||||
<interfacename>SecurityMetadataSource</interfacename>, although this is beyond the scope of
|
||||
this document. Irrespective of the approach used, the
|
||||
<interfacename>SecurityMetadataSource</interfacename> is responsible for returning a
|
||||
<literal>List<ConfigAttribute></literal> containing all of the configuration
|
||||
attributes associated with a single secure HTTP URL.</para>
|
||||
<para>It should be noted that the
|
||||
<literal>FilterSecurityInterceptor.setSecurityMetadataSource()</literal> method actually
|
||||
expects an instance of <interfacename>FilterInvocationDefinitionSource</interfacename>. This
|
||||
is a marker interface which subclasses <interfacename>SecurityMetadataSource</interfacename>.
|
||||
It simply denotes the <interfacename>SecurityMetadataSource</interfacename> understands
|
||||
<classname>FilterInvocation</classname>s. In the interests of simplicity we'll continue to
|
||||
refer to the <interfacename>FilterInvocationDefinitionSource</interfacename> as an
|
||||
<interfacename>SecurityMetadataSource</interfacename>, as the distinction is of little
|
||||
relevance to most users of the <classname>FilterSecurityInterceptor</classname>.</para>
|
||||
<para>When using the namespace option to configure the interceptor, commas are used to delimit
|
||||
the different configuration attributes that apply to each HTTP URL. Each configuration
|
||||
attribute is assigned into its own <literal>SecurityConfig</literal> object. The
|
||||
<literal>SecurityConfig</literal> object is discussed in the High Level Design section. The
|
||||
<interfacename>SecurityMetadataSource</interfacename> created by the property editor,
|
||||
<interfacename>FilterInvocationDefinitionSource</interfacename>, matches configuration
|
||||
attributes against <literal>FilterInvocations</literal> based on expression evaluation of the
|
||||
request URL. Two standard expression syntaxes are supported. The default is to treat all
|
||||
expressions as Apache Ant paths and regular expressions are also supported for ore complex
|
||||
cases. The <literal>path-type</literal> attribute is used to specify the type of pattern being
|
||||
used. It is not possible to mix expression syntaxes within the same definition. For example,
|
||||
the previous configuration using regular expressions instead of Ant paths would be written as
|
||||
follows:</para>
|
||||
<programlisting><![CDATA[
|
||||
<bean id="filterInvocationInterceptor"
|
||||
class="org.springframework.security.intercept.web.FilterSecurityInterceptor">
|
||||
<property name="authenticationManager" ref="authenticationManager"/>
|
||||
<property name="accessDecisionManager" ref="accessDecisionManager"/>
|
||||
<property name="runAsManager" ref="runAsManager"/>
|
||||
<property name="securityMetadataSource">
|
||||
<security:filter-security-metadata-source path-type="regex">
|
||||
<security:intercept-url pattern="\A/secure/super/.*\Z" access="ROLE_WE_DONT_HAVE"/>
|
||||
<security:intercept-url pattern="\A/secure/.*\" access="ROLE_SUPERVISOR,ROLE_TELLER"/>
|
||||
</security:filter-security-metadata-source>
|
||||
</property>
|
||||
</bean>]]> </programlisting>
|
||||
<para>Irrespective of the type of expression syntax used, expressions are always evaluated in
|
||||
the order they are defined. Thus it is important that more specific expressions are defined
|
||||
higher in the list than less specific expressions. This is reflected in our example above,
|
||||
where the more specific <literal>/secure/super/</literal> pattern appears higher than the less
|
||||
specific <literal>/secure/</literal> pattern. If they were reversed, the
|
||||
<literal>/secure/</literal> pattern would always match and the
|
||||
<literal>/secure/super/</literal> pattern would never be evaluated.</para>
|
||||
<para>As with other security interceptors, the <literal>validateConfigAttributes</literal>
|
||||
property is observed. When set to <literal>true</literal> (the default), at startup time the
|
||||
<classname>FilterSecurityInterceptor</classname> will evaluate if the provided configuration
|
||||
attributes are valid. It does this by checking each configuration attribute can be processed
|
||||
by either the <interfacename>AccessDecisionManager</interfacename> or the
|
||||
<literal>RunAsManager</literal>. If neither of these can process a given configuration
|
||||
attribute, an exception is thrown.</para>
|
||||
</section>
|
||||
</chapter>
|
||||
|
|
|
@ -0,0 +1,226 @@
|
|||
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="security-filter-chain"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<info>
|
||||
<title>The Security Filter Chain</title>
|
||||
</info>
|
||||
<para>Spring Security's web infrastructure is based entirely on standard servlet filters. It
|
||||
doesn't use servlets or any other servlet-based frameworks (such as Spring MVC) internally, so
|
||||
it has no strong links to any particular web technology. It deals in
|
||||
<classname>HttpServletRequest</classname>s and <classname>HttpServletResponse</classname>s
|
||||
and doesn't care whether the requests come from a browser, a web service client, an
|
||||
<classname>HttpInvoker</classname> or an AJAX application. </para>
|
||||
<para> Spring Security maintains a filter chain internally where each of the filters has a
|
||||
particular responsibility and filters are added or removed from the configuration depending on
|
||||
which services are required. The ordering of the filters is important as there are
|
||||
dependencies between them. If you have been using <link xlink:href="#ns-config">namespace
|
||||
configuration</link>, then the filters are automatically configured for you and you don't
|
||||
have to define any Spring beans explicitly but here may be times when you want full control
|
||||
over the security filter chain, either because you are using features which aren't supported
|
||||
in the namespace, or you are using your own customized versions of classes.</para>
|
||||
<section xml:id="delegating-filter-proxy">
|
||||
<title><classname>DelegatingFilterProxy</classname></title>
|
||||
<para> When using servlet filters, you obviously need to declare them in your
|
||||
<filename>web.xml</filename>, or they will be ignored by the servlet container. In Spring
|
||||
Security, the filter classes are also Spring beans defined in the application context and
|
||||
thus able to take advantage of Spring's rich dependency-injection facilities and lifecycle
|
||||
interfaces. Spring's <classname>DelegatingFilterProxy</classname> provides the link between
|
||||
<filename>web.xml</filename> and the application context. </para>
|
||||
<para>When using <classname>DelegatingFilterProxy</classname>, you will see something like
|
||||
this in the <filename>web.xml</filename> file: <programlisting><![CDATA[
|
||||
<filter>
|
||||
<filter-name>myFilter</filter-name>
|
||||
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
|
||||
</filter>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>myFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>]]>
|
||||
</programlisting> Notice that the filter is actually a
|
||||
<literal>DelegatingFilterProxy</literal>, and not the class that will actually implement
|
||||
the logic of the filter. What <classname>DelegatingFilterProxy</classname> does is delegate
|
||||
the <interfacename>Filter</interfacename>'s methods through to a bean which is obtained from
|
||||
the Spring application context. This enables the bean to benefit from the Spring web
|
||||
application context lifecycle support and configuration flexibility. The bean must implement
|
||||
<interfacename>javax.servlet.Filter</interfacename> and it must have the same name as that
|
||||
in the <literal>filter-name</literal> element. Read the Javadoc for
|
||||
<classname>DelegatingFilterProxy</classname> for more information</para>
|
||||
</section>
|
||||
<section xml:id="filter-chain-proxy">
|
||||
<title><classname>FilterChainProxy</classname></title>
|
||||
<para> It should now be clear that you can declare each Spring Security filter bean that you
|
||||
require in your application context file and add a corresponding
|
||||
<classname>DelegatingFilterProxy</classname> entry to <filename>web.xml</filename> for
|
||||
each filter, making sure that they are ordered correctly. This is a cumbersome approach and
|
||||
clutters up the <filename>web.xml</filename> file quickly if we have a lot of filters. We
|
||||
would prefer to just add a single entry to <filename>web.xml</filename> and deal entirely
|
||||
with the application context file for managing our web security beans. This is where Spring
|
||||
Secuiryt's <classname>FilterChainProxy</classname> comes in. It is wired using a
|
||||
<literal>DelegatingFilterProxy</literal>, just like in the example above, but with the
|
||||
<literal>filter-name</literal> set to the bean name <quote>filterChainProxy</quote>. The
|
||||
filter chain is then declared in the application context with the same bean name. Here's an
|
||||
example: <programlisting language="xml"><![CDATA[
|
||||
<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
|
||||
<sec:filter-chain-map path-type="ant">
|
||||
<sec:filter-chain pattern="/webServices/**" filters="
|
||||
securityContextPersistenceFilterWithASCFalse,
|
||||
basicProcessingFilter,
|
||||
exceptionTranslationFilter,
|
||||
filterSecurityInterceptor" />
|
||||
<sec:filter-chain pattern="/**" filters="
|
||||
securityContextPersistenceFilterWithASCTrue,
|
||||
authenticationProcessingFilter,
|
||||
exceptionTranslationFilter,
|
||||
filterSecurityInterceptor" />
|
||||
</sec:filter-chain-map>
|
||||
</bean>
|
||||
]]>
|
||||
</programlisting> The namespace element <literal>filter-chain-map</literal> is
|
||||
used to set up the security filter chain(s) which are required within the application<footnote>
|
||||
<para>Note that you'll need to include the security namespace in your application context
|
||||
XML file in order to use this syntax.</para>
|
||||
</footnote>. It maps a particular URL pattern to a chain of filters built up from the bean
|
||||
names specified in the <literal>filters</literal> element. Both regular expressions and Ant
|
||||
Paths are supported, and the most specific URIs appear first. At runtime the
|
||||
<classname>FilterChainProxy</classname> will locate the first URI pattern that matches the
|
||||
current web request and the list of filter beans specified by the <literal>filters</literal>
|
||||
attribute will be applied to that request. The filters will be invoked in the order they are
|
||||
defined, so you have complete control over the filter chain which is applied to a particular
|
||||
URL.</para>
|
||||
<para>You may have noticed we have declared two
|
||||
<classname>SecurityContextPersistenceFilter</classname>s in the filter chain
|
||||
(<literal>ASC</literal> is short for <literal>allowSessionCreation</literal>, a property
|
||||
of <classname>SecurityContextPersistenceFilter</classname>). As web services will never
|
||||
present a <literal>jsessionid</literal> on future requests, creating
|
||||
<literal>HttpSession</literal>s for such user agents would be wasteful. If you had a
|
||||
high-volume application which required maximum scalability, we recommend you use the
|
||||
approach shown above. For smaller applications, using a single
|
||||
<classname>SecurityContextPersistenceFilter</classname> (with its default
|
||||
<literal>allowSessionCreation</literal> as <literal>true</literal>) would likely be
|
||||
sufficient.</para>
|
||||
<para>In relation to lifecycle issues, the <classname>FilterChainProxy</classname> will always
|
||||
delegate <methodname>init(FilterConfig)</methodname> and <methodname>destroy()</methodname>
|
||||
methods through to the underlaying <interfacename>Filter</interfacename>s if such methods
|
||||
are called against <classname>FilterChainProxy</classname> itself. In this case,
|
||||
<classname>FilterChainProxy</classname> guarantees to only initialize and destroy each
|
||||
<literal>Filter</literal> bean once, no matter how many times it is declared in the filter
|
||||
chain(s). You control the overall choice as to whether these methods are called or not via
|
||||
the <literal>targetFilterLifecycle</literal> initialization parameter of
|
||||
<literal>DelegatingFilterProxy</literal>. By default this property is
|
||||
<literal>false</literal> and servlet container lifecycle invocations are not delegated
|
||||
through <literal>DelegatingFilterProxy</literal>.</para>
|
||||
<para> When we looked at how to set up web security using <link
|
||||
xlink:href="#namespace-auto-config">namespace configuration</link>, we used a
|
||||
<literal>DelegatingFilterProxy</literal> with the name
|
||||
<quote>springSecurityFilterChain</quote>. You should now be able to see that this is the
|
||||
name of the <classname>FilterChainProxy</classname> which is created by the namespace. </para>
|
||||
<section>
|
||||
<title>Bypassing the Filter Chain</title>
|
||||
<para> As with the namespace, you can use the attribute <literal>filters = "none"</literal>
|
||||
as an alternative to supplying a filter bean list. This will omit the request pattern from
|
||||
the security filter chain entirely. Note that anything matching this path will then have
|
||||
no authentication or authorization services applied and will be freely accessible. If you
|
||||
want to make use of the contents of the <classname>SecurityContext</classname> contents
|
||||
during a request, then it must have passed through the security filter chain. Otherwise
|
||||
the <classname>SecurityContextHolder</classname> will not have been populated and the
|
||||
contents will be null.</para>
|
||||
</section>
|
||||
</section>
|
||||
<section>
|
||||
<title>Filter Ordering</title>
|
||||
<para>The order that filters are defined in the chain is very important. Irrespective of which
|
||||
filters you are actually using, the order should be as follows:
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
<para><classname>ChannelProcessingFilter</classname>, because it might need to redirect
|
||||
to a different protocol</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><classname>ConcurrentSessionFilter</classname>, because it doesn't use any
|
||||
<classname>SecurityContextHolder</classname> functionality but needs to update the
|
||||
<interfacename>SessionRegistry</interfacename> to reflect ongoing requests from the
|
||||
principal</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><classname>SecurityContextPersistenceFilter</classname>, so a
|
||||
<interfacename>SecurityContext</interfacename> can be set up in the
|
||||
<classname>SecurityContextHolder</classname> at the beginning of a web request, and
|
||||
any changes to the <interfacename>SecurityContext</interfacename> can be copied to the
|
||||
<literal>HttpSession</literal> when the web request ends (ready for use with the
|
||||
next web request)</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Authentication processing mechanisms -
|
||||
<classname>UsernamePasswordAuthenticationProcessingFilter</classname>,
|
||||
<classname>CasProcessingFilter</classname>,
|
||||
<classname>BasicProcessingFilter</classname> etc - so that the
|
||||
<classname>SecurityContextHolder</classname> can be modified to contain a valid
|
||||
<interfacename>Authentication</interfacename> request token</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>The <literal>SecurityContextHolderAwareRequestFilter</literal>, if you are using
|
||||
it to install a Spring Security aware <literal>HttpServletRequestWrapper</literal>
|
||||
into your servlet container</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><classname>RememberMeProcessingFilter</classname>, so that if no earlier
|
||||
authentication processing mechanism updated the
|
||||
<classname>SecurityContextHolder</classname>, and the request presents a cookie that
|
||||
enables remember-me services to take place, a suitable remembered
|
||||
<interfacename>Authentication</interfacename> object will be put there</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><classname>AnonymousProcessingFilter</classname>, so that if no earlier
|
||||
authentication processing mechanism updated the
|
||||
<classname>SecurityContextHolder</classname>, an anonymous
|
||||
<interfacename>Authentication</interfacename> object will be put there</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><classname>ExceptionTranslationFilter</classname>, to catch any Spring Security
|
||||
exceptions so that either an HTTP error response can be returned or an appropriate
|
||||
<interfacename>AuthenticationEntryPoint</interfacename> can be launched</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><classname>FilterSecurityInterceptor</classname>, to protect web URIs and raise
|
||||
exceptions when access is denied</para>
|
||||
</listitem>
|
||||
</orderedlist></para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Use with other Filter-Based Frameworks</title>
|
||||
<para>If you're using some other framework that is also filter-based, then you need to make
|
||||
sure that the Spring Security filters come first. This enables the
|
||||
<classname>SecurityContextHolder</classname> to be populated in time for use by the other
|
||||
filters. Examples are the use of SiteMesh to decorate your web pages or a web framework like
|
||||
Wicket which uses a filter to handle its requests. </para>
|
||||
</section>
|
||||
<!--
|
||||
<section xml:id="taglib">
|
||||
<info>
|
||||
<title>Tag Libraries</title>
|
||||
</info>
|
||||
<para>Spring Security comes bundled with several JSP tag libraries which provide a range of
|
||||
different services.</para>
|
||||
<section xml:id="taglib-config">
|
||||
<info>
|
||||
<title>Configuration</title>
|
||||
</info>
|
||||
<para>All taglib classes are included in the core
|
||||
<literal>spring-security-taglibs-<version>.jar</literal> file, with the
|
||||
<literal>security.tld</literal> located in the JAR's <literal>META-INF</literal>
|
||||
directory. This means for JSP 1.2+ web containers you can simply include the JAR in the
|
||||
WAR's <literal>WEB-INF/lib</literal> directory and it will be available.</para>
|
||||
</section>
|
||||
<section xml:id="taglib-usage">
|
||||
<info>
|
||||
<title>Usage</title>
|
||||
</info>
|
||||
<para>Now that you've configured the tag libraries, refer to the individual reference guide
|
||||
sections for details on how to use them. Note that when using the tags, you should include
|
||||
the taglib reference in your JSP:
|
||||
<programlisting>
|
||||
<%@ taglib prefix='security' uri='http://www.springframework.org/security/tags' %>
|
||||
</programlisting></para>
|
||||
</section>
|
||||
</section>-->
|
||||
</chapter>
|
|
@ -97,7 +97,24 @@
|
|||
Security.</para>
|
||||
</partintro>
|
||||
<xi:include href="technical-overview.xml"/>
|
||||
<xi:include href="web-infrastructure.xml"/>
|
||||
<xi:include href="core-services.xml"/>
|
||||
</part>
|
||||
<part xml:id="web-app-security">
|
||||
<title>Web Application Security</title>
|
||||
<partintro>
|
||||
<para> Most Spring Security users will be using the framework in applications which make user
|
||||
of HTTP and the Servlet API. In this part, we'll take a look at how Spring Security provides
|
||||
authentication and access-control features for the web layer of an application. We'll look
|
||||
behind the facade of the namespace and see which classes and interfaces are actually
|
||||
assembled to provide web-layer security. In some situations it is necessary to use
|
||||
traditional bean configuration to provide full control over the configuration, so we'll also
|
||||
see how to configure these classes directly without the namespace.</para>
|
||||
</partintro>
|
||||
<xi:include href="security-filter-chain.xml"/>
|
||||
<xi:include href="core-filters.xml"/>
|
||||
<xi:include href="basic-and-digest-auth.xml"/>
|
||||
<xi:include href="remember-me-authentication.xml"/>
|
||||
<xi:include href="concurrent-sessions.xml"/>
|
||||
</part>
|
||||
<part xml:id="authentication">
|
||||
<title>Authentication</title>
|
||||
|
@ -120,12 +137,7 @@
|
|||
the project web site.</para>
|
||||
</footnote>. </para>
|
||||
</partintro>
|
||||
<xi:include href="common-auth-services.xml"/>
|
||||
<xi:include href="dao-auth-provider.xml"/>
|
||||
<xi:include href="form-authentication.xml"/>
|
||||
<xi:include href="basic-authentication.xml"/>
|
||||
<xi:include href="digest-authentication.xml"/>
|
||||
|
||||
<xi:include href="anon-auth-provider.xml"/>
|
||||
<xi:include href="runas-auth-provider.xml"/>
|
||||
</part>
|
||||
|
@ -145,24 +157,21 @@
|
|||
</partintro>
|
||||
<xi:include href="authorization-common.xml"/>
|
||||
<xi:include href="secured-objects.xml"/>
|
||||
<xi:include href="domain-acls.xml"/>
|
||||
</part>
|
||||
<part xml:id="advanced-topics">
|
||||
<title>Advanced Topics</title>
|
||||
<!--
|
||||
Essentially standalone features which do not have to follow on directly from earlier chapters
|
||||
-->
|
||||
<partintro>
|
||||
<para>
|
||||
In this part we cover some of the more advanced features of the framework.
|
||||
</para>
|
||||
<partintro>
|
||||
<para> In this part we cover some of the more advanced features of the framework. </para>
|
||||
</partintro>
|
||||
<xi:include href="remember-me-authentication.xml"/>
|
||||
<xi:include href="domain-acls.xml"/>
|
||||
<xi:include href="preauth.xml"/>
|
||||
<xi:include href="ldap-auth-provider.xml"/>
|
||||
<xi:include href="ldap-auth-provider.xml"/>
|
||||
<xi:include href="jaas-auth-provider.xml"/>
|
||||
<xi:include href="cas-auth-provider.xml"/>
|
||||
<xi:include href="x509-auth-provider.xml"/>
|
||||
<xi:include href="cas-auth-provider.xml"/>
|
||||
<xi:include href="x509-auth-provider.xml"/>
|
||||
</part>
|
||||
<xi:include href="appendix-db-schema.xml"/>
|
||||
<xi:include href="appendix-namespace.xml"/>
|
||||
|
|
|
@ -108,8 +108,8 @@ if (principal instanceof UserDetails) {
|
|||
required.</para>
|
||||
<para> On successful authentication, <interfacename>UserDetails</interfacename> is used to
|
||||
build the <interfacename>Authentication</interfacename> object that is stored in the
|
||||
<classname>SecurityContextHolder</classname> (more on this in <link
|
||||
xlink:href="#tech-intro-authentication-mgr"/> below). The good news is that we provide a
|
||||
<classname>SecurityContextHolder</classname> (more on this <link
|
||||
xlink:href="#tech-intro-authentication-mgr">below</link>). The good news is that we provide a
|
||||
number of <interfacename>UserDetailsService</interfacename> implementations, including one
|
||||
that uses an in-memory map (<classname>InMemoryDaoImpl</classname>) and another that uses
|
||||
JDBC (<interfacename>JdbcDaoImpl</interfacename>). Most users tend to write their own,
|
||||
|
@ -321,33 +321,14 @@ Successfully authenticated. Security context contains: \
|
|||
(or equivalent) that reads the third-party user information from a location, build a
|
||||
Spring Security-specific <interfacename>Authentication</interfacename> object, and put it
|
||||
onto the <classname>SecurityContextHolder</classname>.</para>
|
||||
<para>
|
||||
If you're wondering how the <interfacename>AuthenticationManager</interfacename>
|
||||
manager is implemented in a real world example, we'll look at that in
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
<section xml:id="tech-intro-authentication-mgr">
|
||||
<title>The <interfacename>AuthenticationManager</interfacename></title>
|
||||
<para>The <interfacename>AuthenticationManager</interfacename> is just an interface, so the
|
||||
implementation can be anything we choose, but how does it work in practice. What if we need
|
||||
to check multiple authentication databases? The default implementation in Spring Security is
|
||||
called <classname>ProviderManager</classname> and rather than handling the authentication
|
||||
request itself, it delegates to a list of configured
|
||||
<classname>AuthenticationProvider</classname>s, each of which is queried in turn to see if
|
||||
it can perform the authentication. Each provider will either throw an exception or return a
|
||||
fully populated <interfacename>Authentication</interfacename> object. Remember our good
|
||||
friends, <interfacename>UserDetails</interfacename> and
|
||||
<interfacename>UserDetailsService</interfacename>? If not, head back to the previous
|
||||
section and refresh your memory. The most common approach to verifying an authentication
|
||||
request is to load the corresponding <interfacename>UserDetails</interfacename> and check
|
||||
the loaded password against the one that has been entered by the user. This is the approach
|
||||
used by the <classname>DaoAuthenticationProvider</classname>, which is most commonly used to
|
||||
wrap a <interfacename>UserDetailsService</interfacename> to implement an
|
||||
<interfacename>AuthenticationProvider</interfacename>. The loaded
|
||||
<interfacename>UserDetails</interfacename> object - and particularly the
|
||||
<literal>GrantedAuthority</literal>s it contains - will be used when building the fully
|
||||
populated <interfacename>Authentication</interfacename> object which is returned from a
|
||||
successful authentication and stored in the <classname>SecurityContext</classname>.</para>
|
||||
</section>
|
||||
</section>
|
||||
<section>
|
||||
<section xml:id="tech-intro-web-authentication">
|
||||
<title>Authentication in a Web Application</title>
|
||||
<para> Now let's explore the situation where you are using Spring Security in a web application
|
||||
(without <filename>web.xml</filename> security enabled). How is a user authenticated and the
|
||||
|
@ -410,7 +391,7 @@ Successfully authenticated. Security context contains: \
|
|||
<interfacename>AuthenticationEntryPoint</interfacename> (if the principal has not been
|
||||
authenticated and therefore we need to go commence step three).</para>
|
||||
</section>
|
||||
<section xml:id="tech-auth-entry-point">
|
||||
<section xml:id="tech-intro-auth-entry-point">
|
||||
<title>AuthenticationEntryPoint</title>
|
||||
<para>The <interfacename>AuthenticationEntryPoint</interfacename> is responsible for step
|
||||
three in the above list. As you can imagine, each web application will have a default
|
||||
|
@ -438,7 +419,7 @@ Successfully authenticated. Security context contains: \
|
|||
rejected the request, the authentication mechanism will ask the user agent to retry (step
|
||||
two above).</para>
|
||||
</section>
|
||||
<section xml:id="tech-sec-context-persistence">
|
||||
<section xml:id="tech-intro-sec-context-persistence">
|
||||
<title>Storing the <interfacename>SecurityContext</interfacename> between requests</title>
|
||||
<para>Depending on the type of application, there may need to be a strategy in place to store
|
||||
the security context between user operations. In a typical web application, a user logs in
|
||||
|
|
|
@ -1,236 +0,0 @@
|
|||
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="web-infrastructure"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<info>
|
||||
<title>Web Application Infrastructure</title>
|
||||
</info>
|
||||
<para> Most Spring Security users will be using the framework in applications which make user of
|
||||
the HTTP and the Servlet API. In this and the following chapters, we'll take a look at how
|
||||
Spring Security provides authentication and access-control features for the web layer of an
|
||||
application. We'll look behind the facade of the namespace and see which classes and interfaces
|
||||
are actually assembled to provide web-layer security. In some situations it is necessary to use
|
||||
traditional bean configuration to provide full control over the configuration, so we'll also see
|
||||
how to configure these classes directly without the namespace.</para>
|
||||
<section xml:id="filters">
|
||||
<title>Security Filter</title>
|
||||
<para>Spring Security's web infrastructure is based entirely on standard servlet filters. It
|
||||
doesn't use servlets or any other servlet-based frameworks (such as Spring MVC) internally, so
|
||||
it has no strong links to any particular web technology. It deals in
|
||||
<classname>HttpServletRequest</classname>s and <classname>HttpServletResponse</classname>s
|
||||
and doesn't care whether the requests come from a browser, a web service client, an
|
||||
<classname>HttpInvoker</classname> or an AJAX application. </para>
|
||||
<para> Spring Security maintains a filter chain internally where each of the filters has a
|
||||
particular responsibility and filters are added or removed from the configuration depending on
|
||||
which services are required. The ordering of the filters is important as there are
|
||||
dependencies between them. If you have been using <link xlink:href="#ns-config">namespace
|
||||
configuration</link>, then the filters are automatically configured for you and you don't
|
||||
have to define any Spring beans explicitly but here may be times when you want full control
|
||||
over the security filter chain, either because you are using features which aren't supported
|
||||
in the namespace, or you are using your own customized versions of classes.</para>
|
||||
<section xml:id="delegating-filter-proxy">
|
||||
<title><classname>DelegatingFilterProxy</classname></title>
|
||||
<para> When using servlet filters, you obviously need to declare them in your
|
||||
<filename>web.xml</filename>, or they will be ignored by the servlet container. In Spring
|
||||
Security, the filter classes are also Spring beans defined in the application context and
|
||||
thus able to take advantage of Spring's rich dependency-injection facilities and lifecycle
|
||||
interfaces. Spring's <classname>DelegatingFilterProxy</classname> provides the link between
|
||||
<filename>web.xml</filename> and the application context. </para>
|
||||
<para>When using <classname>DelegatingFilterProxy</classname>, you will see something like
|
||||
this in the <filename>web.xml</filename> file: <programlisting><![CDATA[
|
||||
<filter>
|
||||
<filter-name>myFilter</filter-name>
|
||||
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
|
||||
</filter>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>myFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>]]>
|
||||
</programlisting> Notice that the filter is actually a
|
||||
<literal>DelegatingFilterProxy</literal>, and not the class that will actually implement
|
||||
the logic of the filter. What <classname>DelegatingFilterProxy</classname> does is delegate
|
||||
the <interfacename>Filter</interfacename>'s methods through to a bean which is obtained from
|
||||
the Spring application context. This enables the bean to benefit from the Spring web
|
||||
application context lifecycle support and configuration flexibility. The bean must implement
|
||||
<interfacename>javax.servlet.Filter</interfacename> and it must have the same name as that
|
||||
in the <literal>filter-name</literal> element. Read the Javadoc for
|
||||
<classname>DelegatingFilterProxy</classname> for more information</para>
|
||||
</section>
|
||||
<section xml:id="filter-chain-proxy">
|
||||
<title><classname>FilterChainProxy</classname></title>
|
||||
<para> It should now be clear that you can declare each Spring Security filter bean that you
|
||||
require in your application context file and add a corresponding
|
||||
<classname>DelegatingFilterProxy</classname> entry to <filename>web.xml</filename> for
|
||||
each filter, making sure that they are ordered correctly. This is a cumbersome approach and
|
||||
clutters up the <filename>web.xml</filename> file quickly if we have a lot of filters. We
|
||||
would prefer to just add a single entry to <filename>web.xml</filename> and deal entirely
|
||||
with the application context file for managing our web security beans. This is where Spring
|
||||
Secuiryt's <classname>FilterChainProxy</classname> comes in. It is wired using a
|
||||
<literal>DelegatingFilterProxy</literal>, just like in the example above, but with the
|
||||
<literal>filter-name</literal> set to the bean name <quote>filterChainProxy</quote>. The
|
||||
filter chain is then declared in the application context with the same bean name. Here's an
|
||||
example: <programlisting language="xml"><![CDATA[
|
||||
<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
|
||||
<sec:filter-chain-map path-type="ant">
|
||||
<sec:filter-chain pattern="/webServices/**" filters="
|
||||
securityContextPersistenceFilterWithASCFalse,
|
||||
basicProcessingFilter,
|
||||
exceptionTranslationFilter,
|
||||
filterSecurityInterceptor" />
|
||||
<sec:filter-chain pattern="/**" filters="
|
||||
securityContextPersistenceFilterWithASCTrue,
|
||||
authenticationProcessingFilter,
|
||||
exceptionTranslationFilter,
|
||||
filterSecurityInterceptor" />
|
||||
</sec:filter-chain-map>
|
||||
</bean>
|
||||
]]>
|
||||
</programlisting> The namespace element <literal>filter-chain-map</literal> is
|
||||
used to set up the security filter chain(s) which are required within the application<footnote>
|
||||
<para>Note that you'll need to include the security namespace in your application context
|
||||
XML file in order to use this syntax.</para>
|
||||
</footnote>. It maps a particular URL pattern to a chain of filters built up from the bean
|
||||
names specified in the <literal>filters</literal> element. Both regular expressions and Ant
|
||||
Paths are supported, and the most specific URIs appear first. At runtime the
|
||||
<classname>FilterChainProxy</classname> will locate the first URI pattern that matches the
|
||||
current web request and the list of filter beans specified by the <literal>filters</literal>
|
||||
attribute will be applied to that request. The filters will be invoked in the order they are
|
||||
defined, so you have complete control over the filter chain which is applied to a particular
|
||||
URL.</para>
|
||||
<para>You may have noticed we have declared two
|
||||
<classname>SecurityContextPersistenceFilter</classname>s in the filter chain
|
||||
(<literal>ASC</literal> is short for <literal>allowSessionCreation</literal>, a property
|
||||
of <classname>SecurityContextPersistenceFilter</classname>). As web services will never
|
||||
present a <literal>jsessionid</literal> on future requests, creating
|
||||
<literal>HttpSession</literal>s for such user agents would be wasteful. If you had a
|
||||
high-volume application which required maximum scalability, we recommend you use the
|
||||
approach shown above. For smaller applications, using a single
|
||||
<classname>SecurityContextPersistenceFilter</classname> (with its default
|
||||
<literal>allowSessionCreation</literal> as <literal>true</literal>) would likely be
|
||||
sufficient.</para>
|
||||
<para>In relation to lifecycle issues, the <classname>FilterChainProxy</classname> will always
|
||||
delegate <methodname>init(FilterConfig)</methodname> and <methodname>destroy()</methodname>
|
||||
methods through to the underlaying <interfacename>Filter</interfacename>s if such methods
|
||||
are called against <classname>FilterChainProxy</classname> itself. In this case,
|
||||
<classname>FilterChainProxy</classname> guarantees to only initialize and destroy each
|
||||
<literal>Filter</literal> bean once, no matter how many times it is declared in the filter
|
||||
chain(s). You control the overall choice as to whether these methods are called or not via
|
||||
the <literal>targetFilterLifecycle</literal> initialization parameter of
|
||||
<literal>DelegatingFilterProxy</literal>. By default this property is
|
||||
<literal>false</literal> and servlet container lifecycle invocations are not delegated
|
||||
through <literal>DelegatingFilterProxy</literal>.</para>
|
||||
<para> When we looked at how to set up web security using <link
|
||||
xlink:href="#namespace-auto-config">namespace configuration</link>, we used a
|
||||
<literal>DelegatingFilterProxy</literal> with the name
|
||||
<quote>springSecurityFilterChain</quote>. You should now be able to see that this is the
|
||||
name of the <classname>FilterChainProxy</classname> which is created by the namespace. </para>
|
||||
<section>
|
||||
<title>Bypassing the Filter Chain</title>
|
||||
<para> As with the namespace, you can use the attribute <literal>filters = "none"</literal>
|
||||
as an alternative to supplying a filter bean list. This will omit the request pattern from
|
||||
the security filter chain entirely. Note that anything matching this path will then have
|
||||
no authentication or authorization services applied and will be freely accessible. If you
|
||||
want to make use of the contents of the <classname>SecurityContext</classname> contents
|
||||
during a request, then it must have passed through the security filter chain. Otherwise
|
||||
the <classname>SecurityContextHolder</classname> will not have been populated and the
|
||||
contents will be null.</para>
|
||||
</section>
|
||||
</section>
|
||||
<section>
|
||||
<title>Filter Ordering</title>
|
||||
<para>The order that filters are defined in the chain is very important. Irrespective of which
|
||||
filters you are actually using, the order should be as follows: <orderedlist
|
||||
inheritnum="ignore" continuation="restarts">
|
||||
<listitem>
|
||||
<para><classname>ChannelProcessingFilter</classname>, because it might need to redirect
|
||||
to a different protocol</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><classname>ConcurrentSessionFilter</classname>, because it doesn't use any
|
||||
<classname>SecurityContextHolder</classname> functionality but needs to update the
|
||||
<interfacename>SessionRegistry</interfacename> to reflect ongoing requests from the
|
||||
principal</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><classname>SecurityContextPersistenceFilter</classname>, so a
|
||||
<interfacename>SecurityContext</interfacename> can be set up in the
|
||||
<classname>SecurityContextHolder</classname> at the beginning of a web request, and
|
||||
any changes to the <interfacename>SecurityContext</interfacename> can be copied to the
|
||||
<literal>HttpSession</literal> when the web request ends (ready for use with the
|
||||
next web request)</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Authentication processing mechanisms -
|
||||
<classname>UsernamePasswordAuthenticationProcessingFilter</classname>,
|
||||
<classname>CasProcessingFilter</classname>,
|
||||
<classname>BasicProcessingFilter</classname> etc - so that the
|
||||
<classname>SecurityContextHolder</classname> can be modified to contain a valid
|
||||
<interfacename>Authentication</interfacename> request token</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>The <literal>SecurityContextHolderAwareRequestFilter</literal>, if you are using
|
||||
it to install a Spring Security aware <literal>HttpServletRequestWrapper</literal>
|
||||
into your servlet container</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><classname>RememberMeProcessingFilter</classname>, so that if no earlier
|
||||
authentication processing mechanism updated the
|
||||
<classname>SecurityContextHolder</classname>, and the request presents a cookie that
|
||||
enables remember-me services to take place, a suitable remembered
|
||||
<interfacename>Authentication</interfacename> object will be put there</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><classname>AnonymousProcessingFilter</classname>, so that if no earlier
|
||||
authentication processing mechanism updated the
|
||||
<classname>SecurityContextHolder</classname>, an anonymous
|
||||
<interfacename>Authentication</interfacename> object will be put there</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><classname>ExceptionTranslationFilter</classname>, to catch any Spring Security
|
||||
exceptions so that either an HTTP error response can be returned or an appropriate
|
||||
<interfacename>AuthenticationEntryPoint</interfacename> can be launched</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><classname>FilterSecurityInterceptor</classname>, to protect web URIs and raise
|
||||
exceptions when access is denied</para>
|
||||
</listitem>
|
||||
</orderedlist></para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Use with other Filter-Based Frameworks</title>
|
||||
<para>If you're using some other framework that is also filter-based, then you need to make
|
||||
sure that the Spring Security filters come first. This enables the
|
||||
<classname>SecurityContextHolder</classname> to be populated in time for use by the other
|
||||
filters. Examples are the use of SiteMesh to decorate your web pages or a web framework like
|
||||
Wicket which uses a filter to handle its requests. </para>
|
||||
</section>
|
||||
</section>
|
||||
<!--
|
||||
<section xml:id="taglib">
|
||||
<info>
|
||||
<title>Tag Libraries</title>
|
||||
</info>
|
||||
<para>Spring Security comes bundled with several JSP tag libraries which provide a range of
|
||||
different services.</para>
|
||||
<section xml:id="taglib-config">
|
||||
<info>
|
||||
<title>Configuration</title>
|
||||
</info>
|
||||
<para>All taglib classes are included in the core
|
||||
<literal>spring-security-taglibs-<version>.jar</literal> file, with the
|
||||
<literal>security.tld</literal> located in the JAR's <literal>META-INF</literal>
|
||||
directory. This means for JSP 1.2+ web containers you can simply include the JAR in the
|
||||
WAR's <literal>WEB-INF/lib</literal> directory and it will be available.</para>
|
||||
</section>
|
||||
<section xml:id="taglib-usage">
|
||||
<info>
|
||||
<title>Usage</title>
|
||||
</info>
|
||||
<para>Now that you've configured the tag libraries, refer to the individual reference guide
|
||||
sections for details on how to use them. Note that when using the tags, you should include
|
||||
the taglib reference in your JSP:
|
||||
<programlisting>
|
||||
<%@ taglib prefix='security' uri='http://www.springframework.org/security/tags' %>
|
||||
</programlisting></para>
|
||||
</section>
|
||||
</section>-->
|
||||
</chapter>
|
Loading…
Reference in New Issue