|
@@ -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>
|