SEC-1178: New manual chapters
This commit is contained in:
parent
c6b9371029
commit
67a90b36ee
|
@ -0,0 +1,54 @@
|
|||
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0"
|
||||
xml:id="concurrent-sessions" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<info>
|
||||
<title>Concurrent Session Handling</title>
|
||||
</info>
|
||||
<!-- TODO: Expand and refer to namespace options -->
|
||||
<para>Spring Security is able to prevent a principal from concurrently authenticating to the
|
||||
same application more than a specified number of times. Many ISVs take advantage of this to
|
||||
enforce licensing, whilst network administrators like this feature because it helps prevent
|
||||
people from sharing login names. You can, for example, stop user "Batman" from logging onto
|
||||
the web application from two different sessions.</para>
|
||||
<para>To use concurrent session support, you'll need to add the following to
|
||||
<literal>web.xml</literal>: <programlisting><![CDATA[
|
||||
<listener>
|
||||
<listener-class>
|
||||
org.springframework.security.web.session.HttpSessionEventPublisher
|
||||
</listener-class>
|
||||
</listener> ]]>
|
||||
</programlisting></para>
|
||||
<para>In addition, you will need to add the
|
||||
<literal>org.springframework.security.web.authentication.concurrent.ConcurrentSessionFilter</literal>
|
||||
to your <classname>FilterChainProxy</classname>. The
|
||||
<classname>ConcurrentSessionFilter</classname> requires two properties,
|
||||
<literal>sessionRegistry</literal>, which generally points to an instance of
|
||||
<literal>SessionRegistryImpl</literal>, and <literal>expiredUrl</literal>, which points to
|
||||
the page to display when a session has expired.</para>
|
||||
<para>The <literal>web.xml</literal>
|
||||
<literal>HttpSessionEventPublisher</literal> causes an <literal>ApplicationEvent</literal> to
|
||||
be published to the Spring <literal>ApplicationContext</literal> every time a
|
||||
<literal>HttpSession</literal> commences or terminates. This is critical, as it allows the
|
||||
<classname>SessionRegistryImpl</classname> to be notified when a session ends.</para>
|
||||
<para>You will also need to wire up the <classname>ConcurrentSessionControllerImpl</classname>
|
||||
and refer to it from your <literal>ProviderManager</literal> bean:</para>
|
||||
<para>
|
||||
<programlisting><![CDATA[
|
||||
<bean id="authenticationManager"
|
||||
class="org.springframework.security.authentication.ProviderManager">
|
||||
<property name="providers">
|
||||
<!-- your providers go here -->
|
||||
</property>
|
||||
<property name="sessionController" ref="concurrentSessionController"/>
|
||||
</bean>
|
||||
|
||||
<bean id="concurrentSessionController" class=
|
||||
"org.springframework.security.authentication.concurrent.ConcurrentSessionControllerImpl">
|
||||
<property name="maximumSessions" value="1"/>
|
||||
<property name="sessionRegistry">
|
||||
<bean
|
||||
class="org.springframework.security.authentication.concurrent.SessionRegistryImpl"/>
|
||||
<property>
|
||||
</bean>
|
||||
]]></programlisting>
|
||||
</para>
|
||||
</chapter>
|
|
@ -0,0 +1,307 @@
|
|||
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="core-web-filters"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>Core Security Filters</title>
|
||||
<para> There are some key filters which will always be used in a web application which uses
|
||||
Spring Security, so we'll look at these and their supporting classes and interfaces them
|
||||
first. We won't cover every feature, so be sure to look at the Javadoc for them if you want
|
||||
to get the complete picture.</para>
|
||||
<section xml:id="filter-security-interceptor">
|
||||
<title><classname>FilterSecurityInterceptor</classname></title>
|
||||
<para>We've already seen <classname>FilterSecurityInterceptor</classname> briefly when
|
||||
discussing access-control in general (see<link xlink:href="#tech-intro-access-control"
|
||||
/>), and we've already used it with the namespace where the
|
||||
<literal><intercept-url></literal> elements are combined to configure it
|
||||
internally. Now we'll see how to explicitly configure it for use with a
|
||||
<classname>FilterChainProxy</classname>, along with its companion filter
|
||||
<classname>ExceptionTranslationFilter</classname>. A typical configuration example
|
||||
is shown below: <programlisting language="xml"><![CDATA[
|
||||
<bean id="filterSecurityInterceptor"
|
||||
class="org.springframework.security.intercept.web.FilterSecurityInterceptor">
|
||||
<property name="authenticationManager" ref="authenticationManager"/>
|
||||
<property name="accessDecisionManager" ref="accessDecisionManager"/>
|
||||
<property name="securityMetadataSource">
|
||||
<security:filter-security-metadata-source>
|
||||
<security:intercept-url pattern="/secure/super/**" access="ROLE_WE_DONT_HAVE"/>
|
||||
<security:intercept-url pattern="/secure/**" access="ROLE_SUPERVISOR,ROLE_TELLER"/>
|
||||
</security:filter-security-metadata-source>
|
||||
</property>
|
||||
</bean>]]></programlisting></para>
|
||||
<para><classname>FilterSecurityInterceptor</classname> is responsible for handling the
|
||||
security of HTTP resources. It requires a reference to an
|
||||
<interfacename>AuthenticationManager</interfacename> and an
|
||||
<interfacename>AccessDecisionManager</interfacename>. It is also supplied with
|
||||
configuration attributes that apply to different HTTP URL requests. Refer back to <link
|
||||
xlink:href="#tech-intro-config-attributes"/> where we saw these originally.</para>
|
||||
<para>The <classname>FilterSecurityInterceptor</classname> can be configured with
|
||||
configuration attributes in two ways. The first, which is shown above, is using the
|
||||
<literal><filter-security-metadata-source></literal> namespace element. This
|
||||
is similar to the <literal><filter-chain-map></literal> used to configure a
|
||||
<classname>FilterChainProxy</classname> but the
|
||||
<literal><intercept-url></literal> child elements only use the
|
||||
<literal>pattern</literal> and <literal>access</literal> attributes. Commas are used
|
||||
to delimit the different configuration attributes that apply to each HTTP URL. The
|
||||
second option is to write your own
|
||||
<interfacename>SecurityMetadataSource</interfacename>, but this is beyond the scope of
|
||||
this document. Irrespective of the approach used, the
|
||||
<interfacename>SecurityMetadataSource</interfacename> is responsible for returning a
|
||||
<literal>List<ConfigAttribute></literal> containing all of the configuration
|
||||
attributes associated with a single secure HTTP URL.</para>
|
||||
<para>It should be noted that the
|
||||
<literal>FilterSecurityInterceptor.setSecurityMetadataSource()</literal> method
|
||||
actually expects an instance of
|
||||
<interfacename>FilterSecurityMetadataSource</interfacename>. This is a marker
|
||||
interface which subclasses <interfacename>SecurityMetadataSource</interfacename>. It
|
||||
simply denotes the <interfacename>SecurityMetadataSource</interfacename> understands
|
||||
<classname>FilterInvocation</classname>s. In the interests of simplicity we'll
|
||||
continue to refer to the <interfacename>FilterInvocationDefinitionSource</interfacename>
|
||||
as a <interfacename>SecurityMetadataSource</interfacename>, as the distinction is of
|
||||
little relevance to most users.</para>
|
||||
<para>The <interfacename>SecurityMetadataSource</interfacename> created by the namespace
|
||||
syntax obtains the configuration attributes for a particular
|
||||
<classname>FilterInvocation</classname> by matching the request URL against the
|
||||
configured <literal>pattern</literal> attributes. This behaves in the same way as it
|
||||
does for namespace configuration. The default is to treat all expressions as Apache Ant
|
||||
paths and regular expressions are also supported for more complex cases. The
|
||||
<literal>path-type</literal> attribute is used to specify the type of pattern being
|
||||
used. It is not possible to mix expression syntaxes within the same definition. As an
|
||||
example, the previous configuration using regular expressions instead of Ant paths would
|
||||
be written as follows:</para>
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<bean id="filterInvocationInterceptor"
|
||||
class="org.springframework.security.intercept.web.FilterSecurityInterceptor">
|
||||
<property name="authenticationManager" ref="authenticationManager"/>
|
||||
<property name="accessDecisionManager" ref="accessDecisionManager"/>
|
||||
<property name="runAsManager" ref="runAsManager"/>
|
||||
<property name="securityMetadataSource">
|
||||
<security:filter-security-metadata-source path-type="regex">
|
||||
<security:intercept-url pattern="\A/secure/super/.*\Z" access="ROLE_WE_DONT_HAVE"/>
|
||||
<security:intercept-url pattern="\A/secure/.*\" access="ROLE_SUPERVISOR,ROLE_TELLER"/>
|
||||
</security:filter-security-metadata-source>
|
||||
</property>
|
||||
</bean>]]> </programlisting>
|
||||
<para>Patterns are always evaluated in the order they are defined. Thus it is important that
|
||||
more specific patterns are defined higher in the list than less specific patterns. This
|
||||
is reflected in our example above, where the more specific
|
||||
<literal>/secure/super/</literal> pattern appears higher than the less specific
|
||||
<literal>/secure/</literal> pattern. If they were reversed, the
|
||||
<literal>/secure/</literal> pattern would always match and the
|
||||
<literal>/secure/super/</literal> pattern would never be evaluated.</para>
|
||||
<!--
|
||||
TODO: Put in FAQ instead. Or drop.
|
||||
<para>As with other security interceptors, the <literal>validateConfigAttributes</literal>
|
||||
property is observed. When set to <literal>true</literal> (the default), at startup time
|
||||
the <classname>FilterSecurityInterceptor</classname> will evaluate if the provided
|
||||
configuration attributes are valid. It does this by checking each configuration
|
||||
attribute can be processed by either the
|
||||
<interfacename>AccessDecisionManager</interfacename> or the
|
||||
<literal>RunAsManager</literal>. If neither of these can process a particular
|
||||
configuration attribute, an exception is thrown.</para>
|
||||
-->
|
||||
</section>
|
||||
<section xml:id="exception-translation-filter">
|
||||
<title>
|
||||
<classname>ExceptionTranslationFilter</classname></title>
|
||||
<para>The <classname>ExceptionTranslationFilter</classname> sits above the <classname>FilterSecurityInterceptor</classname>
|
||||
in the security filter stack. It doesn't do any actual security enforcement itself,
|
||||
but handles exceptions thrown by the security interceptors and provides suitable
|
||||
and HTTP responses.
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<bean id="exceptionTranslationFilter"
|
||||
class="org.springframework.security.web.access.ExceptionTranslationFilter">
|
||||
<property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
|
||||
<property name="accessDeniedHandler" ref="accessDeniedHandler"/>
|
||||
</bean>
|
||||
|
||||
<bean id="authenticationEntryPoint"
|
||||
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
|
||||
<property name="loginFormUrl" value="/login.jsp"/>
|
||||
</bean>
|
||||
|
||||
<bean id="accessDeniedHandler"
|
||||
class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
|
||||
<property name="errorPage" value="/accessDenied.htm"/>
|
||||
</bean>
|
||||
]]></programlisting>
|
||||
</para>
|
||||
<section xml:id="auth-entry-point">
|
||||
<title><interfacename>AuthenticationEntryPoint</interfacename></title>
|
||||
<para>
|
||||
The <interfacename>AuthenticationEntryPoint</interfacename> will be
|
||||
called if the user requests a secure HTTP resource but they are not authenticated. An
|
||||
appropriate <exceptionname>AuthenticationException</exceptionname> or
|
||||
<exceptionname>AccessDeniedException</exceptionname> will be thrown by a security
|
||||
interceptor further down the call stack, triggering the
|
||||
<methodname>commence</methodname> method on the entry point. This does the job of
|
||||
presenting the appropriate response to the user so that authentication can begin. The
|
||||
one we've used here is <classname>LoginUrlAuthenticationEntryPoint</classname>, which
|
||||
redirects the request to a different URL (typically a login page). The actual
|
||||
implementation used will depend on the authentication mechanism you want to be used in
|
||||
your application. </para>
|
||||
</section>
|
||||
<section xml:id="access-denied-handler">
|
||||
<title><interfacename>AccessDeniedHandler</interfacename></title>
|
||||
<para>What happens if a user is already authenticated an they try to access a protected
|
||||
resource? In normal usage, this shouldn't happen because the application workflow
|
||||
should be restricted to operations to which a user has access. For example, an HTML
|
||||
link to an administration page might be hidden from users who do not have an admin
|
||||
role. You can't rely on hiding links for security though, as there's always a
|
||||
possibility that a user will just enter the URL directly in an attempt to bypass the
|
||||
restrictions. Or they might modify a RESTful URL to change some of the argument
|
||||
values. Your application must be protected against these scenarios or it will
|
||||
definitely be insecure. You will typically use simple web layer security to apply
|
||||
constraints to basic URLs and use more specific method-based security on your
|
||||
service layer interfaces to really nail down what is permissible.</para>
|
||||
<para>If an <exceptionname>AccessDeniedException</exceptionname> is thrown and a user
|
||||
has already been authenticated, then this means that an operation has been attempted
|
||||
for which they don't have enough permissions. In this case,
|
||||
<classname>ExceptionTranslationFilter</classname> will invoke a second strategy,
|
||||
the <interfacename>AccessDeniedHandler</interfacename>. By default, an
|
||||
<classname>AccessDeniedHandlerImpl</classname> is used, which just sends a 403 (Forbidden)
|
||||
response to the client. Alternatively you can configure an instance explicitly (as in
|
||||
the above example) and set an error page URL which it will forwards the request to
|
||||
<footnote><para>We use a forward so that the SecurityContextHolder still contains details of the principal,
|
||||
which may be useful for displaying 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.</para></footnote>.
|
||||
This can be a simple <quote>access denied</quote> page, such as a JSP, or it could be
|
||||
a more complex handler such as an MVC controller. And of course, you can implement the
|
||||
interface yourself and use your own implementation.
|
||||
</para>
|
||||
<para>It's also possible to supply a custom <interfacename>AccessDeniedHandler</interfacename> when you're
|
||||
using the namespace to configure your application. See <link xlink:href="#nsa-access-denied-handler"/>.</para>
|
||||
</section>
|
||||
<section xml:id="security-context-persistence-filter">
|
||||
<title><classname>SecurityContextPersistenceFilter</classname></title>
|
||||
<para>
|
||||
We covered the purpose of this all-important filter in <link xlink:href="#tech-intro-sec-context-persistence"/> so
|
||||
you might want to re-read that section at this point. Let's first take a look at how you would configure it
|
||||
for use with a <classname>FilterChainProxy</classname>. A basic configuration only requires the bean itself
|
||||
<programlisting><![CDATA[
|
||||
<bean id="securityContextPersistenceFilter"
|
||||
class="org.springframework.security.web.context.SecurityContextPersistenceFilter"/>
|
||||
]]></programlisting>
|
||||
As we saw previously, this filter has two main tasks. It is responsible for storage of the <classname>SecurityContext</classname>
|
||||
contents between HTTP requests and for clearing the <classname>SecurityContextHolder</classname> when a request is completed.
|
||||
Clearing the <classname>ThreadLocal</classname> in which the context is stored is essential, as it might otherwise be possible for
|
||||
a thread to be replaced into the servlet container's thread pool, with the security context for a particular user still
|
||||
attached. This thread might then be used at a later stage, performing operations with the wrong credentials.
|
||||
</para>
|
||||
|
||||
<section xml:id="security-context-repository">
|
||||
<title><interfacename>SecurityContextRepository</interfacename></title>
|
||||
<para>From Spring Security 3.0, the job of loading and storing the security context is now delegated
|
||||
to a separate strategy interface:
|
||||
<programlisting language="java">
|
||||
public interface SecurityContextRepository {
|
||||
SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder);
|
||||
void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response);
|
||||
}
|
||||
</programlisting>
|
||||
The <classname>HttpRequestResponseHolder</classname> is simply a container for the incoming request and
|
||||
response objects, allowing the implementation to replace these with wrapper classes. The
|
||||
returned contents will be passed to the filter chain.
|
||||
</para>
|
||||
<para>
|
||||
The default implementation is <classname>HttpSessionSecurityContextRepository</classname>, which
|
||||
stores the security context as an <interfacename>HttpSession</interfacename> attribute
|
||||
<footnote><para>In Spring Security 2.0 and earlier, this filter was called
|
||||
<classname>HttpSessionContextIntegrationFilter</classname> and performed all the work of
|
||||
storing the context was performed by the filter itself. If you were familiar with this class,
|
||||
then most of the configuration options which were available can now be found on
|
||||
<classname>HttpSessionSecurityContextRepository</classname>.
|
||||
</para></footnote>.
|
||||
The most important configuration parameter for this implementation is the
|
||||
<literal>allowSessionCreation</literal> property, which defaults to <literal>true</literal>, thus
|
||||
allowing the class to create a session if it needs one to store the security context for an authenticated
|
||||
user (it won't create one unless authentication has taken place and the contents of the security context have changed).
|
||||
If you don't want a session to be created, then you can set this property to <literal>false</literal>:
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<bean id="securityContextPersistenceFilter"
|
||||
class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
|
||||
<property name='securityContextRepository'>
|
||||
<bean class='org.springframework.security.web.context.HttpSessionSecurityContextRepository'>
|
||||
<property name='allowSessionCreation' value='false' />
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
]]></programlisting>
|
||||
|
||||
Alternatively you could provide a null implementation of the <interfacename>SecurityContextRepository</interfacename> interface.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
<section xml:id="form-login-filter">
|
||||
<title><classname>UsernamePasswordAuthenticationProcessingFilter</classname></title>
|
||||
<para>We've now seen the three main filters which are always present in a Spring Security web configuration. These
|
||||
are also the three which are automatically created by the namespace <literal><http></literal> element and
|
||||
cannot be substituted with alternatives. The only thing that's missing now is an actual authentication mechanism, something
|
||||
that will allow a user to authenticate. This filter is the most commonly used authentication filter and the one
|
||||
that is most often customized
|
||||
<footnote><para>For historical reasons, prior to Spring Security 3.0, this filter was called
|
||||
<classname>AuthenticationProcessingFilter</classname> and the entry point was called
|
||||
<classname>AuthenticationProcessingFilterEntryPoint</classname>. Since the framework now supports
|
||||
many different forms of authentication, they have both been given more specific names in 3.0.</para></footnote>.
|
||||
It also provides the implementation used by the <form-login> element from the namespace.
|
||||
There are three stages required to configure it.
|
||||
<orderedlist>
|
||||
<listitem><para>Configure a <classname>LoginUrlAuthenticationEntryPoint</classname> with the URL
|
||||
of the login page, just as we did above, and set it on the <classname>ExceptionTranslationFilter</classname>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem><para>Implement the login page (using a JSP or MVC controller).</para></listitem>
|
||||
<listitem><para>Configure an instance of <classname>UsernamePasswordAuthenticationProcessingFilter</classname> in the application context</para></listitem>
|
||||
<listitem><para>Add the filter bean to your filter chain proxy (making sure you pay attention to the order). <!-- TODO: link --></para></listitem>
|
||||
</orderedlist>
|
||||
The login form simply contains <literal>j_username</literal> and
|
||||
<literal>j_password</literal> input fields, and posts to the URL that is
|
||||
monitored by the filter (by default this is <literal>/j_spring_security_check</literal>).
|
||||
The basic filter configuration looks something like this:
|
||||
<programlisting><![CDATA[
|
||||
<bean id="authenticationProcessingFilter" class=
|
||||
"org.springframework.security.web.authentication.UsernamePasswordAuthenticationProcessingFilter">
|
||||
<property name="authenticationManager" ref="authenticationManager"/>
|
||||
<property name="filterProcessesUrl" value="/j_spring_security_check"/>
|
||||
</bean> ]]>
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
<section xml:id="form-login-flow-handling">
|
||||
<title>Application Flow on Authentication Success and Failure</title>
|
||||
<para>
|
||||
The filter calls the configured <interfacename>AuthenticationManager</interfacename>
|
||||
processes each authentication request. The destination following a successful authentication
|
||||
or an authentication failure is controlled by the <interfacename>AuthenticationSuccessHandler</interfacename>
|
||||
and <interfacename>AuthenticationFailureHandler</interfacename> strategy interfaces, respectively.
|
||||
The filter has properties which allow you to set these so you can customize the behaviour as
|
||||
much as you want
|
||||
<footnote><para>In versions prior to 3.0, the application flow at this point had evolved to a stage
|
||||
was controlled by a mix of properties on this class and strategy plugins. The
|
||||
decision was made for 3.0 to refactor the code to make these two strategies entirely responsible.
|
||||
</para></footnote>.
|
||||
Some standard implementations are supplied such as
|
||||
<classname>SimpleUrlAuthenticationSuccessHandler</classname>,
|
||||
<classname>SavedRequestAwareAuthenticationSuccessHandler</classname>,
|
||||
<classname>SimpleUrlAuthenticationFailureHandler</classname> and
|
||||
<classname>ExceptionMappingAuthenticationFailureHandler</classname>. Have a look at the Javadoc
|
||||
for these classes to see how they work.
|
||||
</para>
|
||||
|
||||
<para>If authentication is successful, the resulting
|
||||
<interfacename>Authentication</interfacename> object will be placed into the
|
||||
<classname>SecurityContextHolder</classname>.
|
||||
The configured AuthenticationSuccessHandler will then be called to either redirect or forward
|
||||
the user to the approprate destination. By default a <classname>SavedRequestAwareAuthenticationSuccessHandler</classname>
|
||||
is used, which means that the user will be redirected to the original destination they requested before they were asked to
|
||||
login.
|
||||
<note>
|
||||
<para>
|
||||
The <classname>ExceptionTranslationFilter</classname> caches the original request a user makes.
|
||||
When the user authenticates, the request handler makes use of this cached request to obtain the original
|
||||
URL and redirect to it. The original request is then rebuilt and used as an alternative.
|
||||
</para>
|
||||
</note>
|
||||
If authentication fails, the configured <interfacename>AuthenticationFailureHandler</interfacename> will be invoked.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
</chapter>
|
|
@ -0,0 +1,169 @@
|
|||
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="core-services"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>Core Services</title>
|
||||
<para> Now that we have a high-level overview of the Spring Security architecture and its core
|
||||
classes, let's take a closer look at one or two of the core interfaces and their
|
||||
implementations, in particular the <interfacename>AuthenticationManager</interfacename>,
|
||||
<interfacename>UserDetailsService</interfacename> and the
|
||||
<interfacename>AccessDecisionManager</interfacename>. These crop up regularly throughout
|
||||
the remainder of this document so it's important you know how they are configured and how
|
||||
they operate. </para>
|
||||
<section xml:id="authentication-manager">
|
||||
<title>The <interfacename>AuthenticationManager</interfacename>,
|
||||
<classname>ProviderManager</classname> and
|
||||
<classname>AuthenticationProvider</classname>s</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 or a combination of different
|
||||
authentication services such as a database and an LDAP server?</para>
|
||||
<para>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
|
||||
chapter 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 wraps 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>
|
||||
<para> If you are using the namespace, an instance of
|
||||
<classname>ProviderMananger</classname> is created and maintained internally, and
|
||||
you add providers to it either by using the namespace authentication provired elements,
|
||||
or by adding the <literal><custom-authentication-provider></literal> element to a
|
||||
bean (see <link xlink:href="#ns-auth-manager">the namespace chapter</link>). In this
|
||||
case, you should not declare a <classname>ProviderManager</classname> bean in your
|
||||
application context. However, if you are not using the namespace then you would declare
|
||||
it like so: <programlisting language="xml"><![CDATA[
|
||||
<bean id="authenticationManager"
|
||||
class="org.springframework.security.authentication.ProviderManager">
|
||||
<property name="providers">
|
||||
<list>
|
||||
<ref local="daoAuthenticationProvider"/>
|
||||
<ref local="anonymousAuthenticationProvider"/>
|
||||
<ref local="ldapAuthenticationProvider"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>]]></programlisting></para>
|
||||
<para>In the above example we have three providers. They are tried in the order shown (which
|
||||
is implied by the use of a <literal>List</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
|
||||
<exceptionname>ProviderNotFoundException</exceptionname>. If you're interested in
|
||||
learning more about chaining providers, please refer to the
|
||||
<literal>ProviderManager</literal> JavaDocs.</para>
|
||||
<para> Authentication mechanisms such as a web form-login processing filter are injected
|
||||
with a reference to the <interfacename>ProviderManager</interfacename> and will call it
|
||||
to handle their authentication requests. The providers you require will sometimes be
|
||||
interchangeable with the authentication mechanisms, while at other times they will
|
||||
depend on a specific authentication mechanism. For example,
|
||||
<classname>DaoAuthenticationProvider</classname> and
|
||||
<classname>LdapAuthenticationProvider</classname> are compatible with any mechanism
|
||||
which submits a simple username/password authentication request and so will work with
|
||||
form-based logins or HTTP Basic authentication. On the other hand, 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 would
|
||||
be JA-SIG CAS, which uses the notion of a service ticket and so can therefore only be
|
||||
authenticated by a <classname>CasAuthenticationProvider</classname>. You needn't be too
|
||||
concerned about this, 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>
|
||||
</section>
|
||||
<section>
|
||||
<title><interfacename>UserDetailsService</interfacename> Implementations</title>
|
||||
<para>As mentioned in the earlier in this reference guide, most authentication providers
|
||||
take advantage of the <interfacename>UserDetails</interfacename> and
|
||||
<interfacename>UserDetailsService</interfacename> interfaces. Recall that the
|
||||
contract for <interfacename>UserDetailsService</interfacename> is a single
|
||||
method:</para>
|
||||
<para>
|
||||
<programlisting>
|
||||
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>The returned <interfacename>UserDetails</interfacename> is an interface that provides
|
||||
getters that guarantee non-null provision of authentication information such as the
|
||||
username, password, granted authorities and whether the user account 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. They may use the returned
|
||||
<interfacename>UserDetails</interfacename> object just for its
|
||||
<literal>GrantedAuthority</literal> information, because some other system (like
|
||||
LDAP or X.509 or CAS etc) has undertaken the responsibility of actually validating the
|
||||
credentials.</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">
|
||||
<title>In-Memory Authentication</title>
|
||||
<para>Is easy to use create a custom <interfacename>UserDetailsService</interfacename>
|
||||
implementation that extracts information from a persistence engine of choice, but
|
||||
many applications do not require such complexity. This is particularly true if
|
||||
you're building a prototype application 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 supports the use of an external properties
|
||||
file: <programlisting><![CDATA[
|
||||
<user-service id="userDetailsService" properties="users.properties"/>
|
||||
]]></programlisting> The properties file should contain entries in the form
|
||||
<programlisting>username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]</programlisting>
|
||||
For example
|
||||
<programlisting>
|
||||
jimi=jimispassword,ROLE_USER,ROLE_ADMIN,enabled
|
||||
bob=bobspassword,ROLE_USER,enabled</programlisting></para>
|
||||
</section>
|
||||
<section xml:id="jdbc-service">
|
||||
<title><literal>JdbcDaoImpl</literal></title>
|
||||
<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 language="xml"><![CDATA[
|
||||
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
|
||||
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
|
||||
<property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/>
|
||||
<property name="username" value="sa"/>
|
||||
<property name="password" value=""/>
|
||||
</bean>
|
||||
|
||||
<bean id="userDetailsService" class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
|
||||
<property name="dataSource" ref="dataSource"/>
|
||||
</bean> ]]> </programlisting>
|
||||
</para>
|
||||
<para>You can use different relational database management systems by modifying the
|
||||
<literal>DriverManagerDataSource</literal> shown above. You can also use a
|
||||
global data source obtained from JNDI, as with any other Spring configuration. </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>
|
||||
</chapter>
|
|
@ -0,0 +1,252 @@
|
|||
<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>
|
||||
|
||||
<section xml:id="filters">
|
||||
<title>The Security Filter Chain</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>
|
||||
<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>
|
||||
|
||||
<section xml:id="authentication-taglibs">
|
||||
<info>
|
||||
<title>Authentication Tag Libraries</title>
|
||||
</info>
|
||||
<para><literal>AuthenticationTag</literal> is used to simply output a property of the current
|
||||
<interfacename>Authentication</interfacename> object to the web page.</para>
|
||||
<para>The following JSP fragment illustrates how to use the
|
||||
<literal>AuthenticationTag</literal>:</para>
|
||||
<para>
|
||||
<programlisting><security:authentication property="principal.username"/></programlisting>
|
||||
</para>
|
||||
<para>This tag would cause the principal's name to be output. Here we are assuming the
|
||||
<literal>Authentication.getPrincipal()</literal> is a
|
||||
<interfacename>UserDetails</interfacename> object, which is generally the case when using
|
||||
one of Spring Security's stadard <classname>AuthenticationProvider</classname>
|
||||
implementations.</para>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
-->
|
||||
</chapter>
|
Loading…
Reference in New Issue