mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-05-30 08:42:13 +00:00
Intermediate ref manual commits
This commit is contained in:
parent
d5aec71fac
commit
8d4c09c191
@ -1,139 +1,71 @@
|
||||
<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>
|
||||
|
||||
<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>In the web.xml, this application will need a single Spring
|
||||
Security filter in order to use the FilterChainProxy. Nearly every
|
||||
Spring Security application will have such an entry, and it looks like
|
||||
this:</para>
|
||||
|
||||
<para><programlisting><![CDATA[
|
||||
<filter>
|
||||
<filter-name>filterChainProxy</filter-name>
|
||||
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
|
||||
</filter>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>filterChainProxy</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>]]>
|
||||
</programlisting></para>
|
||||
|
||||
<para>The above declarations will cause every web request to be passed
|
||||
through to the bean called <literal>filterChainProxy</literal>
|
||||
which will usually be an instance of Spring Security's
|
||||
<classname>FilterChainProxy</classname>.
|
||||
As explained in the filters section of this reference guide, the
|
||||
<classname>FilterChainProxy</classname> is a generally-useful class
|
||||
that enables web requests to be passed to different filters based on
|
||||
URL patterns. Those delegated filters are managed inside the
|
||||
application context, so they can benefit from dependency injection.
|
||||
Let's have a look at what the FilterChainProxy bean definition would
|
||||
look like inside your application context:</para>
|
||||
|
||||
<para><programlisting><![CDATA[
|
||||
<bean id="filterChainProxy"
|
||||
class="org.springframework.security.web.FilterChainProxy">
|
||||
<security:filter-chain-map path-type="ant">
|
||||
<security:filter-chain pattern="/**" filters="
|
||||
securityContextPersistenceFilter,
|
||||
logoutFilter,
|
||||
authenticationProcessingFilter,
|
||||
basicProcessingFilter,
|
||||
securityContextHolderAwareRequestFilter,
|
||||
rememberMeProcessingFilter,
|
||||
anonymousProcessingFilter,
|
||||
exceptionTranslationFilter,
|
||||
filterInvocationInterceptor,
|
||||
switchUserProcessingFilter"/>
|
||||
</security:filter-chain-map>
|
||||
</bean>]]></programlisting></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>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>
|
||||
|
||||
<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[
|
||||
<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">
|
||||
@ -143,60 +75,47 @@
|
||||
<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>
|
||||
|
||||
</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[
|
||||
<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"/>
|
||||
@ -211,132 +130,105 @@
|
||||
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>
|
||||
</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>
|
||||
<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>
|
||||
|
||||
</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>
|
||||
<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[
|
||||
<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[
|
||||
</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>
|
||||
]]></programlisting> The properties file should contain entries in the form
|
||||
<programlisting>
|
||||
username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]
|
||||
</programlisting>
|
||||
For example
|
||||
<programlisting>
|
||||
<programlisting>
|
||||
jimi=jimispassword,ROLE_USER,ROLE_ADMIN,enabled
|
||||
bob=bobspassword,ROLE_USER,enabled
|
||||
</programlisting>
|
||||
</para>
|
||||
</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>
|
||||
<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"/>
|
||||
@ -347,21 +239,17 @@
|
||||
|
||||
<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.
|
||||
</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>
|
||||
<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,
|
||||
@ -375,66 +263,49 @@
|
||||
|
||||
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>
|
||||
</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[
|
||||
<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>
|
||||
|
||||
</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>
|
||||
|
||||
<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>
|
||||
|
||||
<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"
|
||||
@ -453,25 +324,24 @@
|
||||
class="org.springframework.security.authentication.concurrent.SessionRegistryImpl"/>
|
||||
<property>
|
||||
</bean>
|
||||
]]></programlisting></para>
|
||||
]]></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>
|
||||
|
||||
<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>
|
||||
<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>
|
||||
</chapter>
|
||||
|
@ -1,450 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="ca"><info><title>Container Adapter Authentication</title></info>
|
||||
|
||||
|
||||
<section xml:id="ca-overview">
|
||||
<info><title>Overview</title></info>
|
||||
|
||||
|
||||
<para>Very early versions of Spring Security exclusively used
|
||||
Container Adapters for interfacing authentication with end users.
|
||||
Whilst this worked well, it required considerable time to support
|
||||
multiple container versions and the configuration itself was
|
||||
relatively time-consuming for developers. For this reason the HTTP
|
||||
Form Authentication and HTTP Basic Authentication approaches were
|
||||
developed, and are today recommended for almost all
|
||||
applications.</para>
|
||||
|
||||
<para>Container Adapters enable Spring Security to integrate directly
|
||||
with the containers used to host end user applications. This
|
||||
integration means that applications can continue to leverage the
|
||||
authentication and authorization capabilities built into containers
|
||||
(such as <literal>isUserInRole()</literal> and form-based or basic
|
||||
authentication), whilst benefiting from the enhanced security
|
||||
interception capabilities provided by Spring Security (it should be
|
||||
noted that Spring Security also offers
|
||||
<literal>ContextHolderAwareRequestWrapper</literal> to deliver
|
||||
<literal>isUserInRole()</literal> and similar Servlet Specification
|
||||
compatibility methods).</para>
|
||||
|
||||
<para>The integration between a container and Spring Security is
|
||||
achieved through an adapter. The adapter provides a
|
||||
container-compatible user authentication provider, and needs to return
|
||||
a container-compatible user object.</para>
|
||||
|
||||
<para>The adapter is instantiated by the container and is defined in a
|
||||
container-specific configuration file. The adapter then loads a Spring
|
||||
application context which defines the normal authentication manager
|
||||
settings, such as the authentication providers that can be used to
|
||||
authenticate the request. The application context is usually named
|
||||
<literal>acegisecurity.xml</literal> and is placed in a
|
||||
container-specific location.</para>
|
||||
|
||||
<para>Spring Security currently supports Jetty, Catalina (Tomcat),
|
||||
JBoss and Resin. Additional container adapters can easily be
|
||||
written</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="ca-adapter"><info><title>Adapter Authentication Provider</title></info>
|
||||
|
||||
|
||||
<para>As is always the case, the container adapter generated
|
||||
<interfacename>Authentication</interfacename> object still needs to be
|
||||
authenticated by an <interfacename>AuthenticationManager</interfacename> when
|
||||
requested to do so by the
|
||||
<classname>AbstractSecurityInterceptor</classname>. The
|
||||
<interfacename>AuthenticationManager</interfacename> needs to be certain the
|
||||
adapter-provided <interfacename>Authentication</interfacename> object is valid and
|
||||
was actually authenticated by a trusted adapter.</para>
|
||||
|
||||
<para>Adapters create <interfacename>Authentication</interfacename> objects which
|
||||
are immutable and implement the <literal>AuthByAdapter</literal>
|
||||
interface. These objects store the hash of a key that is defined by
|
||||
the adapter. This allows the <interfacename>Authentication</interfacename> object
|
||||
to be validated by the <literal>AuthByAdapterProvider</literal>. This
|
||||
authentication provider is defined as follows:</para>
|
||||
|
||||
<para><programlisting><bean id="authByAdapterProvider"
|
||||
class="org.springframework.security.adapters.AuthByAdapterProvider">
|
||||
<property name="key"><value>my_password</value></property>
|
||||
</bean> </programlisting></para>
|
||||
|
||||
<para>The key must match the key that is defined in the
|
||||
container-specific configuration file that starts the adapter. The
|
||||
<literal>AuthByAdapterProvider</literal> automatically accepts as
|
||||
valid any <literal>AuthByAdapter</literal> implementation that returns
|
||||
the expected hash of the key.</para>
|
||||
|
||||
<para>To reiterate, this means the adapter will perform the initial
|
||||
authentication using providers such as
|
||||
<literal>DaoAuthenticationProvider</literal>, returning an
|
||||
<literal>AuthByAdapter</literal> instance that contains a hash code of
|
||||
the key. Later, when an application calls a security interceptor
|
||||
managed resource, the <literal>AuthByAdapter</literal> instance in the
|
||||
<interfacename>SecurityContext</interfacename> in the
|
||||
<classname>SecurityContextHolder</classname> will be tested by the
|
||||
application's <literal>AuthByAdapterProvider</literal>. There is no
|
||||
requirement for additional authentication providers such as
|
||||
<literal>DaoAuthenticationProvider</literal> within the
|
||||
application-specific application context, as the only type of
|
||||
<interfacename>Authentication</interfacename> instance that will be presented by
|
||||
the application is from the container adapter.</para>
|
||||
|
||||
<para>Classloader issues are frequent with containers and the use of
|
||||
container adapters illustrates this further. Each container requires a
|
||||
very specific configuration. The installation instructions are
|
||||
provided below. Once installed, please take the time to try the sample
|
||||
application to ensure your container adapter is properly
|
||||
configured.</para>
|
||||
|
||||
<para>When using container adapters with the
|
||||
<literal>DaoAuthenticationProvider</literal>, ensure you set its
|
||||
<literal>forcePrincipalAsString</literal> property to
|
||||
<literal>true</literal>.</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="ca-jetty"><info><title>Jetty</title></info>
|
||||
|
||||
|
||||
<para>The following was tested with Jetty 4.2.18.</para>
|
||||
|
||||
<para><literal>$JETTY_HOME</literal> refers to the root of your Jetty
|
||||
installation.</para>
|
||||
|
||||
<para>Edit your <literal>$JETTY_HOME/etc/jetty.xml</literal> file so
|
||||
the <literal><Configure class></literal> section has a new
|
||||
<literal>addRealm</literal> call:</para>
|
||||
|
||||
<para><programlisting>
|
||||
<Call name="addRealm">
|
||||
<Arg>
|
||||
<New class="org.springframework.security.adapters.jetty.JettySpringSecurityUserRealm">
|
||||
<Arg>Spring Powered Realm</Arg>
|
||||
<Arg>my_password</Arg>
|
||||
<Arg>etc/acegisecurity.xml</Arg>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
|
||||
</programlisting></para>
|
||||
|
||||
<para>Copy <literal>acegisecurity.xml</literal> into
|
||||
<literal>$JETTY_HOME/etc</literal>.</para>
|
||||
|
||||
<para>Copy the following files into
|
||||
<literal>$JETTY_HOME/ext</literal>:<itemizedlist>
|
||||
<listitem>
|
||||
<para><literal>aopalliance.jar</literal></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>commons-logging.jar</literal></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>spring.jar</literal></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>acegi-security-jetty-XX.jar</literal></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>commons-codec.jar</literal></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>burlap.jar</literal></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>hessian.jar</literal></para>
|
||||
</listitem>
|
||||
</itemizedlist></para>
|
||||
|
||||
<para>None of the above JAR files (or
|
||||
<literal>acegi-security-XX.jar</literal>) should be in your
|
||||
application's <literal>WEB-INF/lib</literal>. The realm name indicated
|
||||
in your <literal>web.xml</literal> does matter with Jetty. The
|
||||
<literal>web.xml</literal> must express the same
|
||||
<literal><realm-name></literal> as your
|
||||
<literal>jetty.xml</literal> (in the example above, "Spring Powered
|
||||
Realm").</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="ca-jboss"><info><title>JBoss</title></info>
|
||||
|
||||
|
||||
<para>The following was tested with JBoss 3.2.6.</para>
|
||||
|
||||
<para><literal>$JBOSS_HOME</literal> refers to the root of your JBoss
|
||||
installation.</para>
|
||||
|
||||
<para>There are two different ways of making spring context available
|
||||
to the Jboss integration classes.</para>
|
||||
|
||||
<para>The first approach is by editing your
|
||||
<literal>$JBOSS_HOME/server/your_config/conf/login-config.xml</literal>
|
||||
file so that it contains a new entry under the
|
||||
<literal><Policy></literal> section:</para>
|
||||
|
||||
<para><programlisting>
|
||||
<application-policy name = "SpringPoweredRealm">
|
||||
<authentication>
|
||||
<login-module code = "org.springframework.security.adapters.jboss.JbossSpringSecurityLoginModule"
|
||||
flag = "required">
|
||||
<module-option name = "appContextLocation">acegisecurity.xml</module-option>
|
||||
<module-option name = "key">my_password</module-option>
|
||||
</login-module>
|
||||
</authentication>
|
||||
</application-policy>
|
||||
|
||||
</programlisting></para>
|
||||
|
||||
<para>Copy <literal>acegisecurity.xml</literal> into
|
||||
<literal>$JBOSS_HOME/server/your_config/conf</literal>.</para>
|
||||
|
||||
<para>In this configuration <literal>acegisecurity.xml</literal>
|
||||
contains the spring context definition including all the
|
||||
authentication manager beans. You have to bear in mind though, that
|
||||
<interfacename>SecurityContext</interfacename> is created and destroyed on each
|
||||
login request, so the login operation might become costly.
|
||||
Alternatively, the second approach is to use Spring singleton
|
||||
capabilities through
|
||||
<literal>org.springframework.beans.factory.access.SingletonBeanFactoryLocator</literal>.
|
||||
The required configuration for this approach is:</para>
|
||||
|
||||
<para><programlisting>
|
||||
<application-policy name = "SpringPoweredRealm">
|
||||
<authentication>
|
||||
<login-module code = "org.springframework.security.adapters.jboss.JbossSpringSecurityLoginModule"
|
||||
flag = "required">
|
||||
<module-option name = "singletonId">springRealm</module-option>
|
||||
<module-option name = "key">my_password</module-option>
|
||||
<module-option name = "authenticationManager">authenticationManager</module-option>
|
||||
</login-module>
|
||||
</authentication>
|
||||
</application-policy>
|
||||
|
||||
</programlisting></para>
|
||||
|
||||
<para>In the above code fragment,
|
||||
<literal>authenticationManager</literal> is a helper property that
|
||||
defines the expected name of the
|
||||
<interfacename>AuthenticationManager</interfacename> in case you have several
|
||||
defined in the IoC container. The <literal>singletonId</literal>
|
||||
property references a bean defined in a
|
||||
<literal>beanRefFactory.xml</literal> file. This file needs to be
|
||||
available from anywhere on the JBoss classpath, including
|
||||
<literal>$JBOSS_HOME/server/your_config/conf</literal>. The
|
||||
<literal>beanRefFactory.xml</literal> contains the following
|
||||
declaration:</para>
|
||||
|
||||
<para><programlisting>
|
||||
<beans>
|
||||
<bean id="springRealm" singleton="true" lazy-init="true" class="org.springframework.context.support.ClassPathXmlApplicationContext">
|
||||
<constructor-arg>
|
||||
<list>
|
||||
<value>acegisecurity.xml</value>
|
||||
</list>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
</beans>
|
||||
|
||||
</programlisting></para>
|
||||
|
||||
<para>Finally, irrespective of the configuration approach you need to
|
||||
copy the following files into
|
||||
<literal>$JBOSS_HOME/server/your_config/lib</literal>:<itemizedlist>
|
||||
<listitem>
|
||||
<para><literal>aopalliance.jar</literal></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>spring.jar</literal></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>acegi-security-jboss-XX.jar</literal></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>commons-codec.jar</literal></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>burlap.jar</literal></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>hessian.jar</literal></para>
|
||||
</listitem>
|
||||
</itemizedlist></para>
|
||||
|
||||
<para>None of the above JAR files (or
|
||||
<literal>acegi-security-XX.jar</literal>) should be in your
|
||||
application's <literal>WEB-INF/lib</literal>. The realm name indicated
|
||||
in your <literal>web.xml</literal> does not matter with JBoss.
|
||||
However, your web application's
|
||||
<literal>WEB-INF/jboss-web.xml</literal> must express the same
|
||||
<literal><security-domain></literal> as your
|
||||
<literal>login-config.xml</literal>. For example, to match the above
|
||||
example, your <literal>jboss-web.xml</literal> would look like
|
||||
this:</para>
|
||||
|
||||
<para><programlisting>
|
||||
<jboss-web>
|
||||
<security-domain>java:/jaas/SpringPoweredRealm</security-domain>
|
||||
</jboss-web></programlisting></para>
|
||||
|
||||
<para>JBoss is a widely-used container adapter (mostly due to the need
|
||||
to support legacy EJBs), so please let us know if you have any
|
||||
difficulties.</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="ca-resin"><info><title>Resin</title></info>
|
||||
|
||||
|
||||
<para>The following was tested with Resin 3.0.6.</para>
|
||||
|
||||
<para><literal>$RESIN_HOME</literal> refers to the root of your Resin
|
||||
installation.</para>
|
||||
|
||||
<para>Resin provides several ways to support the container adapter. In
|
||||
the instructions below we have elected to maximise consistency with
|
||||
other container adapter configurations. This will allow Resin users to
|
||||
simply deploy the sample application and confirm correct
|
||||
configuration. Developers comfortable with Resin are naturally able to
|
||||
use its capabilities to package the JARs with the web application
|
||||
itself, and/or support single sign-on.</para>
|
||||
|
||||
<para>Copy the following files into
|
||||
<literal>$RESIN_HOME/lib</literal>:<itemizedlist>
|
||||
<listitem>
|
||||
<para><literal>aopalliance.jar</literal></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>commons-logging.jar</literal></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>spring.jar</literal></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>acegi-security-resin-XX.jar</literal></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>commons-codec.jar</literal></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>burlap.jar</literal></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>hessian.jar</literal></para>
|
||||
</listitem>
|
||||
</itemizedlist></para>
|
||||
|
||||
<para>Unlike the container-wide <literal>acegisecurity.xml</literal>
|
||||
files used by other container adapters, each Resin web application
|
||||
will contain its own
|
||||
<literal>WEB-INF/resin-acegisecurity.xml</literal> file. Each web
|
||||
application will also contain a <literal>resin-web.xml</literal> file
|
||||
which Resin uses to start the container adapter:</para>
|
||||
|
||||
<para><programlisting>
|
||||
<web-app>
|
||||
<authenticator>
|
||||
<type>org.springframework.security.adapters.resin.ResinAcegiAuthenticator</type>
|
||||
<init>
|
||||
<app-context-location>WEB-INF/resin-acegisecurity.xml</app-context-location>
|
||||
<key>my_password</key>
|
||||
</init>
|
||||
</authenticator>
|
||||
</web-app>
|
||||
|
||||
</programlisting></para>
|
||||
|
||||
<para>With the basic configuration provided above, none of the JAR
|
||||
files listed (or <literal>acegi-security-XX.jar</literal>) should be
|
||||
in your application's <literal>WEB-INF/lib</literal>. The realm name
|
||||
indicated in your <literal>web.xml</literal> does not matter with
|
||||
Resin, as the relevant authentication class is indicated by the
|
||||
<literal><authenticator></literal> setting</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="ca-tomcat"><info><title>Tomcat</title></info>
|
||||
|
||||
|
||||
<para>The following was tested with Jakarta Tomcat 4.1.30 and
|
||||
5.0.19.</para>
|
||||
|
||||
<para><literal>$CATALINA_HOME</literal> refers to the root of your
|
||||
Catalina (Tomcat) installation.</para>
|
||||
|
||||
<para>Edit your <literal>$CATALINA_HOME/conf/server.xml</literal> file
|
||||
so the <literal><Engine></literal> section contains only one
|
||||
active <literal><Realm></literal> entry. An example realm
|
||||
entry:</para>
|
||||
|
||||
<para><programlisting> <Realm
|
||||
className="org.springframework.security.adapters.catalina.CatalinaSpringSecurityUserRealm"
|
||||
appContextLocation="conf/acegisecurity.xml"
|
||||
key="my_password" /></programlisting></para>
|
||||
|
||||
<para>Be sure to remove any other <literal><Realm></literal>
|
||||
entry from your <literal><Engine></literal> section.</para>
|
||||
|
||||
<para>Copy <literal>acegisecurity.xml</literal> into
|
||||
<literal>$CATALINA_HOME/conf</literal>.</para>
|
||||
|
||||
<para>Copy <literal>spring-security-catalina-XX.jar</literal> into
|
||||
<literal>$CATALINA_HOME/server/lib</literal>.</para>
|
||||
|
||||
<para>Copy the following files into
|
||||
<literal>$CATALINA_HOME/common/lib</literal>:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><literal>aopalliance.jar</literal></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>spring.jar</literal></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>commons-codec.jar</literal></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>burlap.jar</literal></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>hessian.jar</literal></para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>None of the above JAR files (or
|
||||
<literal>spring-security-XX.jar</literal>) should be in your
|
||||
application's <literal>WEB-INF/lib</literal>. The realm name indicated
|
||||
in your <literal>web.xml</literal> does not matter with
|
||||
Catalina.</para>
|
||||
|
||||
<para>We have received reports of problems using this Container
|
||||
Adapter with Mac OS X. A work-around is to use a script such as
|
||||
follows:</para>
|
||||
|
||||
<para><programlisting>#!/bin/sh
|
||||
export CATALINA_HOME="/Library/Tomcat"
|
||||
export JAVA_HOME="/Library/Java/Home"
|
||||
cd /
|
||||
$CATALINA_HOME/bin/startup.sh</programlisting></para>
|
||||
|
||||
<para>Finally, restart Tomcat.</para>
|
||||
</section>
|
||||
</chapter>
|
@ -681,8 +681,8 @@
|
||||
<para> We've touched on the idea that the namespace configuration automatically registers an
|
||||
authentication manager bean for you. This is an instance of Spring Security's
|
||||
<classname>ProviderManager</classname> class, which you may already be familiar with if
|
||||
you've used the framework before. You can't use a custom
|
||||
<classname>AuthenticationManager</classname> if you are using either HTTP or method security
|
||||
you've used the framework before. If not, it will be covered later, in <link xlink:href="#tech-intro-authentication"/>.
|
||||
You can't use a custom <classname>AuthenticationManager</classname> if you are using either HTTP or method security
|
||||
through the namespace, but this should not be a problem as you have full control over the
|
||||
<classname>AuthenticationProvider</classname>s that are used. </para>
|
||||
<para> You may want to register additional <classname>AuthenticationProvider</classname> beans
|
||||
|
@ -86,7 +86,7 @@
|
||||
<xi:include href="community.xml"/>
|
||||
</part>
|
||||
<part xml:id="overall-architecture">
|
||||
<title>Overall Architecture</title>
|
||||
<title>Architecture and Implementation</title>
|
||||
<partintro>
|
||||
<para>Once you are familiar with setting up and running some namespace-configuration based
|
||||
applications, you may wish to develop more of an understanding of how the framework actually
|
||||
@ -97,23 +97,7 @@
|
||||
Security.</para>
|
||||
</partintro>
|
||||
<xi:include href="technical-overview.xml"/>
|
||||
<!--xi:include href="supporting-infrastructure.xml"/-->
|
||||
<!-- xi:include href="channel-security.xml"/ -->
|
||||
</part>
|
||||
|
||||
<part xml:id="webapp-security" >
|
||||
<title>Web Application Security</title>
|
||||
<partintro>
|
||||
<para>
|
||||
Most Spring Security users will be using the framework in enterprise applications which
|
||||
make user of the 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="supporting-infrastructure.xml"/>
|
||||
<xi:include href="web-infrastructure.xml"/>
|
||||
</part>
|
||||
<part xml:id="authentication">
|
||||
<title>Authentication</title>
|
||||
@ -138,16 +122,11 @@
|
||||
</partintro>
|
||||
<xi:include href="common-auth-services.xml"/>
|
||||
<xi:include href="dao-auth-provider.xml"/>
|
||||
<xi:include href="ldap-auth-provider.xml"/>
|
||||
<xi:include href="form-authentication.xml"/>
|
||||
<xi:include href="basic-authentication.xml"/>
|
||||
<xi:include href="digest-authentication.xml"/>
|
||||
<xi:include href="remember-me-authentication.xml"/>
|
||||
<xi:include href="jaas-auth-provider.xml"/>
|
||||
<xi:include href="preauth.xml"/>
|
||||
|
||||
<xi:include href="anon-auth-provider.xml"/>
|
||||
<xi:include href="x509-auth-provider.xml"/>
|
||||
<xi:include href="cas-auth-provider.xml"/>
|
||||
<xi:include href="runas-auth-provider.xml"/>
|
||||
</part>
|
||||
<part xml:id="authorization">
|
||||
@ -168,6 +147,23 @@
|
||||
<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>
|
||||
<xi:include href="remember-me-authentication.xml"/>
|
||||
<xi:include href="preauth.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"/>
|
||||
</part>
|
||||
<xi:include href="appendix-db-schema.xml"/>
|
||||
<xi:include href="appendix-namespace.xml"/>
|
||||
</book>
|
||||
|
@ -1,260 +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 Security Infrastructure</title></info>
|
||||
|
||||
<section xml:id="filters">
|
||||
<title>Spring Security Filters</title>
|
||||
|
||||
<para>Spring Security's web application features are implemented using 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
|
||||
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 the target class is <classname>org.springframework.security.web.FilterChainProxy</classname>.
|
||||
The filter chain is then declared in the application context. 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. 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.
|
||||
</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 setup 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</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Use with other Filter-Based Frameworks</title>
|
||||
<para>If you're using SiteMesh, ensure Spring Security filters execute
|
||||
before the SiteMesh filters are called. This enables the
|
||||
<classname>SecurityContextHolder</classname> to be populated in time for
|
||||
use by SiteMesh decorators.</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-xx.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. If
|
||||
you're using a JSP 1.1 container, you'll need to declare the JSP
|
||||
taglib in your <literal>web.xml file</literal>, and include
|
||||
<literal>security.tld</literal> in the <literal>WEB-INF/lib</literal>
|
||||
directory. The following fragment is added to
|
||||
<literal>web.xml</literal>:
|
||||
<programlisting><![CDATA[
|
||||
<taglib>
|
||||
<taglib-uri>http://www.springframework.org/security/tags</taglib-uri>
|
||||
<taglib-location>/WEB-INF/security.tld</taglib-location>
|
||||
</taglib>
|
||||
]]></programlisting></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>
|
@ -1,44 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="taglib">
|
||||
<info><title>Tag Libraries</title></info>
|
||||
|
||||
|
||||
<section xml:id="taglib-overview">
|
||||
<info><title>Overview</title></info>
|
||||
<para>Spring Security comes bundled with several JSP tag libraries
|
||||
that eases JSP writing. The tag libraries provide a range of different
|
||||
services.</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="taglib-config">
|
||||
<info><title>Configuration</title></info>
|
||||
<para>All taglib classes are included in the core
|
||||
<literal>spring-security-xx.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. If
|
||||
you're using a JSP 1.1 container, you'll need to declare the JSP
|
||||
taglib in your <literal>web.xml file</literal>, and include
|
||||
<literal>security.tld</literal> in the <literal>WEB-INF/lib</literal>
|
||||
directory. The following fragment is added to
|
||||
<literal>web.xml</literal>:</para>
|
||||
|
||||
<para><programlisting>
|
||||
<taglib>
|
||||
<taglib-uri>http://www.springframework.org/security/tags</taglib-uri>
|
||||
<taglib-location>/WEB-INF/security.tld</taglib-location>
|
||||
</taglib>
|
||||
</programlisting></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>
|
||||
</chapter>
|
@ -1,4 +1,5 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="technical-overview">
|
||||
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="technical-overview"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<info>
|
||||
<title>Technical Overview</title>
|
||||
</info>
|
||||
@ -98,18 +99,25 @@ if (principal instanceof UserDetails) {
|
||||
answer is that there is a special interface called
|
||||
<interfacename>UserDetailsService</interfacename>. The only method on this interface
|
||||
accepts a <literal>String</literal>-based username argument and returns a
|
||||
<interfacename>UserDetails</interfacename>. Most authentication providers that ship with
|
||||
Spring Security delegate to a <interfacename>UserDetailsService</interfacename> as part of
|
||||
the authentication process. The <interfacename>UserDetailsService</interfacename> is used to
|
||||
<interfacename>UserDetails</interfacename>:
|
||||
<programlisting language="java">
|
||||
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
|
||||
</programlisting>
|
||||
This is the most common approach to loading information for a user within Spring Security
|
||||
and you will see it used throughout the framework whenever information on a user is
|
||||
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>. The good news is that we provide a number of
|
||||
<interfacename>UserDetailsService</interfacename> implementations, including one that uses
|
||||
an in-memory map and another that uses JDBC. Most users tend to write their own, though,
|
||||
with their implementations often simply sitting on top of an existing Data Access Object
|
||||
(DAO) that represents their employees, customers, or other users of the enterprise
|
||||
application. Remember the advantage that whatever your UserDetailsService returns can always
|
||||
be obtained from the <classname>SecurityContextHolder</classname>, as per the above code
|
||||
fragment.</para>
|
||||
<classname>SecurityContextHolder</classname> (more on this in <link
|
||||
xlink:href="#tech-intro-authentication-mgr"/> below). 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,
|
||||
though, with their implementations often simply sitting on top of an existing Data Access
|
||||
Object (DAO) that represents their employees, customers, or other users of the application.
|
||||
Remember the advantage that whatever your <interfacename>UserDetailsService</interfacename>
|
||||
returns can always be obtained from the <classname>SecurityContextHolder</classname> using
|
||||
the above code fragment. </para>
|
||||
</section>
|
||||
<section xml:id="tech-granted-authority">
|
||||
<title>GrantedAuthority</title>
|
||||
@ -222,8 +230,8 @@ if (principal instanceof UserDetails) {
|
||||
the returned authentication object.</para>
|
||||
</listitem>
|
||||
</orderedlist>From that point on, the user is considered to be authenticated. Let's look at
|
||||
some code as an
|
||||
example.<programlisting language="java">import org.springframework.security.authentication.*;
|
||||
some code as an example.
|
||||
<programlisting language="java">import org.springframework.security.authentication.*;
|
||||
import org.springframework.security.core.*;
|
||||
import org.springframework.security.core.authority.GrantedAuthorityImpl;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
@ -268,8 +276,8 @@ class SampleAuthenticationManager implements AuthenticationManager {
|
||||
throw new BadCredentialsException("Bad Credentials");
|
||||
}
|
||||
}</programlisting>Here
|
||||
we have written a little program that asks the user to enter a username and password
|
||||
and performs the above sequence. The <interfacename>AuthenticationManager</interfacename> which
|
||||
we have written a little program that asks the user to enter a username and password and
|
||||
performs the above sequence. The <interfacename>AuthenticationManager</interfacename> which
|
||||
we've implemented here will authenticate any user whose username and password are the same.
|
||||
It assigns a single role to every user. The output from the above will be something
|
||||
like:<programlisting>
|
||||
@ -290,8 +298,8 @@ Successfully authenticated. Security context contains: \
|
||||
</programlisting></para>
|
||||
<para>Note that you don't normally need to write any code like this. The process will normally
|
||||
occur internally, in a web authentication filter for example. We've just included the code
|
||||
here to show that the question of what actually constitutes authentication in Spring Security
|
||||
has quite a simple answer. A user is authenticated when the
|
||||
here to show that the question of what actually constitutes authentication in Spring
|
||||
Security has quite a simple answer. A user is authenticated when the
|
||||
<classname>SecurityContextHolder</classname> contains a fully populated
|
||||
<interfacename>Authentiation</interfacename> object.</para>
|
||||
<section>
|
||||
@ -314,138 +322,141 @@ Successfully authenticated. Security context contains: \
|
||||
Spring Security-specific <interfacename>Authentication</interfacename> object, and put it
|
||||
onto the <classname>SecurityContextHolder</classname>.</para>
|
||||
</section>
|
||||
<section>
|
||||
<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. Most <classname>AuthenticationProvider</classname>s will
|
||||
ask a <interfacename>UserDetailsService</interfacename> to provide a
|
||||
<interfacename>UserDetails</interfacename> object. The resulting
|
||||
<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.</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>
|
||||
<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
|
||||
security context established?</para>
|
||||
<para>Consider a typical web application's authentication process:</para>
|
||||
<orderedlist inheritnum="ignore" continuation="restarts">
|
||||
<listitem>
|
||||
<para>You visit the home page, and click on a link.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>A request goes to the server, and the server decides that you've asked for a protected
|
||||
resource.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>As you're not presently authenticated, the server sends back a response indicating
|
||||
that you must authenticate. The response will either be an HTTP response code, or a
|
||||
redirect to a particular web page.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Depending on the authentication mechanism, your browser will either redirect to the
|
||||
specific web page so that you can fill out the form, or the browser will somehow retrieve
|
||||
your identity (via a BASIC authentication dialogue box, a cookie, a X.509 certificate
|
||||
etc.).</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>The browser will send back a response to the server. This will either be an HTTP POST
|
||||
containing the contents of the form that you filled out, or an HTTP header containing your
|
||||
authentication details.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Next the server will decide whether or not the presented credentials are valid. If
|
||||
they're valid, the next step will happen. If they're invalid, usually your browser will be
|
||||
asked to try again (so you return to step two above).</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>The original request that you made to cause the authentication process will be
|
||||
retried. Hopefully you've authenticated with sufficient granted authorities to access the
|
||||
protected resource. If you have sufficient access, the request will be successful.
|
||||
Otherwise, you'll receive back an HTTP error code 403, which means "forbidden".</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
<para>Spring Security has distinct classes responsible for most of the steps described above.
|
||||
The main participants (in the order that they are used) are the
|
||||
<classname>ExceptionTranslationFilter</classname>, an
|
||||
<interfacename>AuthenticationEntryPoint</interfacename> and an <quote>authentication
|
||||
mechanism</quote>, which is resposible for calling the
|
||||
<classname>AuthenticationManager</classname> which we saw in the previous section.</para>
|
||||
<section>
|
||||
<title>ExceptionTranslationFilter</title>
|
||||
<para><classname>ExceptionTranslationFilter</classname> is a Spring Security filter that has
|
||||
responsibility for detecting any Spring Security exceptions that are thrown. Such exceptions
|
||||
will generally be thrown by an <classname>AbstractSecurityInterceptor</classname>, which is
|
||||
the main provider of authorization services. We will discuss
|
||||
<classname>AbstractSecurityInterceptor</classname> in the next section, but for now we
|
||||
just need to know that it produces Java exceptions and knows nothing about HTTP or how to go
|
||||
about authenticating a principal. Instead the
|
||||
<classname>ExceptionTranslationFilter</classname> offers this service, with specific
|
||||
responsibility for either returning error code 403 (if the principal has been authenticated
|
||||
and therefore simply lacks sufficient access - as per step seven above), or launching an
|
||||
<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">
|
||||
<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
|
||||
authentication strategy (well, this can be configured like nearly everything else in Spring
|
||||
Security, but let's keep it simple for now). Each major authentication system will have its
|
||||
own <interfacename>AuthenticationEntryPoint</interfacename> implementation, which typically
|
||||
performs one of the actions described in step 3.</para>
|
||||
</section>
|
||||
<section>
|
||||
<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 security context established?</para>
|
||||
<para>Consider a typical web application's authentication process:</para>
|
||||
<orderedlist inheritnum="ignore" continuation="restarts">
|
||||
<listitem>
|
||||
<para>You visit the home page, and click on a link.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>A request goes to the server, and the server decides that you've asked for a
|
||||
protected resource.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>As you're not presently authenticated, the server sends back a response indicating
|
||||
that you must authenticate. The response will either be an HTTP response code, or a
|
||||
redirect to a particular web page.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Depending on the authentication mechanism, your browser will either redirect to the
|
||||
specific web page so that you can fill out the form, or the browser will somehow
|
||||
retrieve your identity (via a BASIC authentication dialogue box, a cookie, a X.509
|
||||
certificate etc.).</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>The browser will send back a response to the server. This will either be an HTTP
|
||||
POST containing the contents of the form that you filled out, or an HTTP header
|
||||
containing your authentication details.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Next the server will decide whether or not the presented credentials are valid. If
|
||||
they're valid, the next step will happen. If they're invalid, usually your browser will
|
||||
be asked to try again (so you return to step two above).</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>The original request that you made to cause the authentication process will be
|
||||
retried. Hopefully you've authenticated with sufficient granted authorities to access
|
||||
the protected resource. If you have sufficient access, the request will be successful.
|
||||
Otherwise, you'll receive back an HTTP error code 403, which means "forbidden".</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
<para>Spring Security has distinct classes responsible for most of the steps described above.
|
||||
The main participants (in the order that they are used) are the
|
||||
<classname>ExceptionTranslationFilter</classname>, an
|
||||
<interfacename>AuthenticationEntryPoint</interfacename> and an <quote>authentication
|
||||
mechanism</quote>, which is resposible for calling the
|
||||
<classname>AuthenticationManager</classname> which we saw in the previous section.</para>
|
||||
<section>
|
||||
<title>ExceptionTranslationFilter</title>
|
||||
<para><classname>ExceptionTranslationFilter</classname> is a Spring Security filter that has
|
||||
responsibility for detecting any Spring Security exceptions that are thrown. Such
|
||||
exceptions will generally be thrown by an
|
||||
<classname>AbstractSecurityInterceptor</classname>, which is the main provider of
|
||||
authorization services. We will discuss <classname>AbstractSecurityInterceptor</classname>
|
||||
in the next section, but for now we just need to know that it produces Java exceptions and
|
||||
knows nothing about HTTP or how to go about authenticating a principal. Instead the
|
||||
<classname>ExceptionTranslationFilter</classname> offers this service, with specific
|
||||
responsibility for either returning error code 403 (if the principal has been
|
||||
authenticated and therefore simply lacks sufficient access - as per step seven above), or
|
||||
launching an <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">
|
||||
<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
|
||||
authentication strategy (well, this can be configured like nearly everything else in
|
||||
Spring Security, but let's keep it simple for now). Each major authentication system will
|
||||
have its own <interfacename>AuthenticationEntryPoint</interfacename> implementation, which
|
||||
typically performs one of the actions described in step 3.</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Authentication Mechanism</title>
|
||||
<para>Once your browser submits your authentication credentials (either as an HTTP form post
|
||||
or HTTP header) there needs to be something on the server that <quote>collects</quote>
|
||||
these authentication details. By now we're at step six in the above list. In Spring
|
||||
Security we have a special name for the function of collecting authentication details from
|
||||
a user agent (usually a web browser), referring to it as the <quote>authentication
|
||||
mechanism</quote>. Examples are form-base login and Basic authentication. Once the
|
||||
authentication details have been collected from the user agent, an
|
||||
<interfacename>Authentication</interfacename>
|
||||
<quote>request</quote> object is built and then presented to the
|
||||
<interfacename>AuthenticationManager</interfacename>.</para>
|
||||
<para>After the authentication mechanism receives back the fully-populated
|
||||
<interfacename>Authentication</interfacename> object, it will deem the request valid,
|
||||
put the <interfacename>Authentication</interfacename> into the
|
||||
<classname>SecurityContextHolder</classname>, and cause the original request to be
|
||||
retried (step seven above). If, on the other hand, the
|
||||
<classname>AuthenticationManager</classname> 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">
|
||||
<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 once and is subsequently identified by their session Id. The server caches the
|
||||
principal information for the duration session. In Spring Security, the responsibility for
|
||||
storing the <interfacename>SecurityContext</interfacename> between requests falls to the
|
||||
<classname>SecurityContextPersistenceFilter</classname>, which by default stores the
|
||||
context as an <literal>HttpSession</literal> attribute between HTTP requests. It restores
|
||||
the context to the <classname>SecurityContextHolder</classname> for each request and,
|
||||
crucially, clears the <classname>SecurityContextHolder</classname> when the request
|
||||
completes. You shouldn't interact directly with the <literal>HttpSession</literal> for
|
||||
security purposes. There is simply no justification for doing so - always use the
|
||||
<classname>SecurityContextHolder</classname> instead. </para>
|
||||
<para> Many other types of application (for example, a stateless RESTful web service) do not
|
||||
use HTTP sessions and will re-authenticate on every request. However, it is still
|
||||
important that the <classname>SecurityContextPersistenceFilter</classname> is included in
|
||||
the chain to make sure that the <classname>SecurityContextHolder</classname> is cleared
|
||||
after each request.</para>
|
||||
</section>
|
||||
<title>Authentication Mechanism</title>
|
||||
<para>Once your browser submits your authentication credentials (either as an HTTP form post
|
||||
or HTTP header) there needs to be something on the server that <quote>collects</quote> these
|
||||
authentication details. By now we're at step six in the above list. In Spring Security we
|
||||
have a special name for the function of collecting authentication details from a user agent
|
||||
(usually a web browser), referring to it as the <quote>authentication mechanism</quote>.
|
||||
Examples are form-base login and Basic authentication. Once the authentication details have
|
||||
been collected from the user agent, an <interfacename>Authentication</interfacename>
|
||||
<quote>request</quote> object is built and then presented to the
|
||||
<interfacename>AuthenticationManager</interfacename>.</para>
|
||||
<para>After the authentication mechanism receives back the fully-populated
|
||||
<interfacename>Authentication</interfacename> object, it will deem the request valid, put
|
||||
the <interfacename>Authentication</interfacename> into the
|
||||
<classname>SecurityContextHolder</classname>, and cause the original request to be retried
|
||||
(step seven above). If, on the other hand, the <classname>AuthenticationManager</classname>
|
||||
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">
|
||||
<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
|
||||
once and is subsequently identified by their session Id. The server caches the principal
|
||||
information for the duration session. In Spring Security, the responsibility for storing the
|
||||
<interfacename>SecurityContext</interfacename> between requests falls to the
|
||||
<classname>SecurityContextPersistenceFilter</classname>, which by default stores the
|
||||
context as an <literal>HttpSession</literal> attribute between HTTP requests. It restores
|
||||
the context to the <classname>SecurityContextHolder</classname> for each request and,
|
||||
crucially, clears the <classname>SecurityContextHolder</classname> when the request
|
||||
completes. You shouldn't interact directly with the <literal>HttpSession</literal> for
|
||||
security purposes. There is simply no justification for doing so - always use the
|
||||
<classname>SecurityContextHolder</classname> instead. </para>
|
||||
<para> Many other types of application (for example, a stateless RESTful web service) do not
|
||||
use HTTP sessions and will re-authenticate on every request. However, it is still important
|
||||
that the <classname>SecurityContextPersistenceFilter</classname> is included in the chain to
|
||||
make sure that the <classname>SecurityContextHolder</classname> is cleared after each
|
||||
request.</para>
|
||||
</section>
|
||||
</section>
|
||||
<section xml:id="tech-intro-access-control">
|
||||
@ -470,9 +481,9 @@ Successfully authenticated. Security context contains: \
|
||||
help you protect method invocations as well as web requests. Most people are interested in
|
||||
securing method invocations on their services layer. This is because the services layer is
|
||||
where most business logic resides in current-generation J2EE applications. If you just need
|
||||
to secure method invocations in the services layer, Spring's standard AOP (otherwise known
|
||||
as AOP Alliance) will be adequate. If you need to secure domain objects directly, you will
|
||||
likely find that AspectJ is worth considering.</para>
|
||||
to secure method invocations in the services layer, Spring's standard AOP will be adequate.
|
||||
If you need to secure domain objects directly, you will likely find that AspectJ is worth
|
||||
considering.</para>
|
||||
<para>You can elect to perform method authorization using AspectJ or Spring AOP, or you can
|
||||
elect to perform web request authorization using filters. You can use zero, one, two or
|
||||
three of these approaches together. The mainstream usage pattern is to perform some web
|
||||
@ -515,11 +526,12 @@ Successfully authenticated. Security context contains: \
|
||||
the invocation has returned.</para>
|
||||
</listitem>
|
||||
</orderedlist></para>
|
||||
<section>
|
||||
<section xml:id="tech-intro-config-attributes">
|
||||
<title>What are Configuration Attributes?</title>
|
||||
<para> A <quote>configuration attribute</quote> can be thought of as a String that has
|
||||
special meaning to the classes used by <classname>AbstractSecurityInterceptor</classname>.
|
||||
They may be simple role names or have more complex meaning, depending on the how
|
||||
They are represented by the interface <interfacename>ConfigAttribute</interfacename> within
|
||||
the framework. They may be simple role names or have more complex meaning, depending on the how
|
||||
sophisticated the <interfacename>AccessDecisionManager</interfacename> implementation is.
|
||||
The <classname>AbstractSecurityInterceptor</classname> is configured with a
|
||||
<interfacename>SecurityMetadataSource</interfacename> which it uses to look up the
|
||||
@ -550,11 +562,11 @@ Successfully authenticated. Security context contains: \
|
||||
<classname>AbstractSecurityInterceptor</classname> gets one final chance to handle the
|
||||
invocation. At this stage the <classname>AbstractSecurityInterceptor</classname> is
|
||||
interested in possibly modifying the return object. We might want this to happen because
|
||||
an authorization decision couldn't be made <quote>on the way in</quote> to a secure object invocation.
|
||||
Being highly pluggable, <classname>AbstractSecurityInterceptor</classname> will pass
|
||||
control to an <literal>AfterInvocationManager</literal> to actually modify the object if
|
||||
needed. This class can even entirely replace the object, or throw an exception, or not
|
||||
change it in any way as it chooses.</para>
|
||||
an authorization decision couldn't be made <quote>on the way in</quote> to a secure object
|
||||
invocation. Being highly pluggable, <classname>AbstractSecurityInterceptor</classname>
|
||||
will pass control to an <literal>AfterInvocationManager</literal> to actually modify the
|
||||
object if needed. This class can even entirely replace the object, or throw an exception,
|
||||
or not change it in any way as it chooses.</para>
|
||||
<para><classname>AbstractSecurityInterceptor</classname> and its related objects are shown
|
||||
in <xref linkend="abstract-security-interceptor"/>. <figure
|
||||
xml:id="abstract-security-interceptor">
|
||||
@ -582,65 +594,48 @@ Successfully authenticated. Security context contains: \
|
||||
</section>
|
||||
<section xml:id="localization">
|
||||
<title>Localization</title>
|
||||
<para>Spring Security supports localization of exception messages that
|
||||
end users are likely to see. If your application is designed for
|
||||
English-speaking users, you don't need to do anything as by default all
|
||||
Security Security messages are in English. If you need to support
|
||||
other locales, everything you need to know is contained in this
|
||||
section.</para>
|
||||
|
||||
<para>All exception messages can be localized, including messages
|
||||
related to authentication failures and access being denied
|
||||
(authorization failures). Exceptions and logging that is focused on
|
||||
developers or system deployers (including incorrect attributes,
|
||||
interface contract violations, using incorrect constructors, startup
|
||||
time validation, debug-level logging) etc are not localized and
|
||||
instead are hard-coded in English within Spring Security's
|
||||
code.</para>
|
||||
|
||||
<para>Shipping in the <literal>spring-security-core-xx.jar</literal> you
|
||||
will find an <literal>org.springframework.security</literal> package
|
||||
that in turn contains a <literal>messages.properties</literal> file.
|
||||
This should be referred to by your
|
||||
<literal>ApplicationContext</literal>, as Spring Security classes
|
||||
implement Spring's <literal>MessageSourceAware</literal> interface and
|
||||
expect the message resolver to be dependency injected at application
|
||||
context startup time. Usually all you need to do is register a bean
|
||||
inside your application context to refer to the messages. An example
|
||||
is shown below:</para>
|
||||
|
||||
<para><programlisting><![CDATA[
|
||||
<para>Spring Security supports localization of exception messages that end users are likely to
|
||||
see. If your application is designed for English-speaking users, you don't need to do anything
|
||||
as by default all Security Security messages are in English. If you need to support other
|
||||
locales, everything you need to know is contained in this section.</para>
|
||||
<para>All exception messages can be localized, including messages related to authentication
|
||||
failures and access being denied (authorization failures). Exceptions and logging that is
|
||||
focused on developers or system deployers (including incorrect attributes, interface contract
|
||||
violations, using incorrect constructors, startup time validation, debug-level logging) etc
|
||||
are not localized and instead are hard-coded in English within Spring Security's code.</para>
|
||||
<para>Shipping in the <literal>spring-security-core-xx.jar</literal> you will find an
|
||||
<literal>org.springframework.security</literal> package that in turn contains a
|
||||
<literal>messages.properties</literal> file. This should be referred to by your
|
||||
<literal>ApplicationContext</literal>, as Spring Security classes implement Spring's
|
||||
<literal>MessageSourceAware</literal> interface and expect the message resolver to be
|
||||
dependency injected at application context startup time. Usually all you need to do is
|
||||
register a bean inside your application context to refer to the messages. An example is shown
|
||||
below:</para>
|
||||
<para>
|
||||
<programlisting><![CDATA[
|
||||
<bean id="messageSource"
|
||||
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
|
||||
<property name="basename" value="org/springframework/security/messages"/>
|
||||
</bean>
|
||||
]]></programlisting></para>
|
||||
|
||||
<para>The <literal>messages.properties</literal> is named in
|
||||
accordance with standard resource bundles and represents the default
|
||||
language supported by Spring Security messages. This default file is
|
||||
in English. If you do not register a message source, Spring Security
|
||||
will still work correctly and fallback to hard-coded English versions
|
||||
of the messages.</para>
|
||||
|
||||
<para>If you wish to customize the
|
||||
<literal>messages.properties</literal> file, or support other
|
||||
languages, you should copy the file, rename it accordingly, and
|
||||
register it inside the above bean definition. There are not a large
|
||||
number of message keys inside this file, so localization should not be
|
||||
considered a major initiative. If you do perform localization of this
|
||||
file, please consider sharing your work with the community by logging
|
||||
a JIRA task and attaching your appropriately-named localized version
|
||||
of <literal>messages.properties</literal>.</para>
|
||||
|
||||
<para>Rounding out the discussion on localization is the Spring
|
||||
<literal>ThreadLocal</literal> known as
|
||||
<classname>org.springframework.context.i18n.LocaleContextHolder</classname>.
|
||||
You should set the <classname>LocaleContextHolder</classname> to represent
|
||||
the preferred <literal>Locale</literal> of each user. Spring Security
|
||||
will attempt to locate a message from the message source using the
|
||||
<literal>Locale</literal> obtained from this
|
||||
<literal>ThreadLocal</literal>. Please refer to the Spring Framework documentation
|
||||
for further details on using <literal>LocaleContextHolder</literal>.</para>
|
||||
</section>
|
||||
]]></programlisting>
|
||||
</para>
|
||||
<para>The <literal>messages.properties</literal> is named in accordance with standard resource
|
||||
bundles and represents the default language supported by Spring Security messages. This
|
||||
default file is in English. If you do not register a message source, Spring Security will
|
||||
still work correctly and fallback to hard-coded English versions of the messages.</para>
|
||||
<para>If you wish to customize the <literal>messages.properties</literal> file, or support other
|
||||
languages, you should copy the file, rename it accordingly, and register it inside the above
|
||||
bean definition. There are not a large number of message keys inside this file, so
|
||||
localization should not be considered a major initiative. If you do perform localization of
|
||||
this file, please consider sharing your work with the community by logging a JIRA task and
|
||||
attaching your appropriately-named localized version of
|
||||
<literal>messages.properties</literal>.</para>
|
||||
<para>Rounding out the discussion on localization is the Spring <literal>ThreadLocal</literal>
|
||||
known as <classname>org.springframework.context.i18n.LocaleContextHolder</classname>. You
|
||||
should set the <classname>LocaleContextHolder</classname> to represent the preferred
|
||||
<literal>Locale</literal> of each user. Spring Security will attempt to locate a message
|
||||
from the message source using the <literal>Locale</literal> obtained from this
|
||||
<literal>ThreadLocal</literal>. Please refer to the Spring Framework documentation for
|
||||
further details on using <literal>LocaleContextHolder</literal>.</para>
|
||||
</section>
|
||||
</chapter>
|
||||
|
236
docs/manual/src/docbook/web-infrastructure.xml
Normal file
236
docs/manual/src/docbook/web-infrastructure.xml
Normal file
@ -0,0 +1,236 @@
|
||||
<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…
x
Reference in New Issue
Block a user