|
@@ -1,347 +0,0 @@
|
|
-<chapter xmlns="http://docbook.org/ns/docbook" version="5.0"
|
|
|
|
- xml:id="authentication-common-auth-services" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
|
|
- <info>
|
|
|
|
- <title>Common Authentication Services</title>
|
|
|
|
- </info>
|
|
|
|
- <section xml:id="mechanisms-providers-entry-points">
|
|
|
|
- <info>
|
|
|
|
- <title>Mechanisms, Providers and Entry Points</title>
|
|
|
|
- </info>
|
|
|
|
- <para>To use Spring Security's authentication services, you'll usually need to configure a web
|
|
|
|
- filter, together with an <classname>AuthenticationProvider</classname> and
|
|
|
|
- <interfacename>AuthenticationEntryPoint</interfacename>. In this section we are going to
|
|
|
|
- explore an example application that needs to support both form-based authentication (so a nice
|
|
|
|
- HTML page is presented to a user for them to login) and BASIC authentication (so a web service
|
|
|
|
- or similar can access protected resources).</para>
|
|
|
|
- <para>The <literal>filter-chain-map</literal> syntax from the security namespace allows you to
|
|
|
|
- define the mapping from URLs to filter chains, using a sequence of
|
|
|
|
- <literal>filter-chain</literal> child elements. Each of these defines a set of URLs using
|
|
|
|
- the <literal>pattern</literal> attribute and a chain of filters using the
|
|
|
|
- <literal>filters</literal> attribute.What's important to note at this stage is that a series
|
|
|
|
- of filters will be run - in the order specified by the declaration - and each of those filters
|
|
|
|
- are actually the <literal>id</literal> of another bean in the application context. So, in our
|
|
|
|
- case some extra beans will also appear in the application context, and they'll be named
|
|
|
|
- <literal>httpSessionContextIntegrationFilter</literal>, <literal>logoutFilter</literal> and
|
|
|
|
- so on. The order that the filters should appear is discussed in the filters section of the
|
|
|
|
- reference guide - although they are correct in the above example.</para>
|
|
|
|
- <para>In our example we have the
|
|
|
|
- <literal>UsernamePasswordAuthenticationProcessingFilter</literal> and
|
|
|
|
- <literal>BasicProcessingFilter</literal> being used. These are the "authentication
|
|
|
|
- mechanisms" that respond to form-based authentication and BASIC HTTP header-based
|
|
|
|
- authentication respectively (we discussed the role of authentication mechanisms earlier in
|
|
|
|
- this reference guide). If you weren't using form or BASIC authentication, neither of these
|
|
|
|
- beans would be defined. You'd instead define filters applicable to your desired authentication
|
|
|
|
- environment, such as <literal>DigestProcessingFilter</literal> or
|
|
|
|
- <literal>CasProcessingFilter</literal>. Refer to the individual chapters of this part of the
|
|
|
|
- reference guide to learn how to configure each of these authentication mechanisms.</para>
|
|
|
|
- <para>Recall that <classname>HttpSessionContextIntegrationFilter</classname> keeps the contents
|
|
|
|
- of the <interfacename>SecurityContext</interfacename> between invocations inside an HTTP
|
|
|
|
- session. This means the authentication mechanisms are only used once, being when the principal
|
|
|
|
- initially tries to authenticate. The rest of the time the authentication mechanisms sit there
|
|
|
|
- and silently pass the request through to the next filter in the chain. That is a practical
|
|
|
|
- requirement due to the fact that few authentication approaches present credentials on each and
|
|
|
|
- every call (BASIC authentication being a notable exception), but what happens if a principal's
|
|
|
|
- account gets cancelled or disabled or otherwise changed (eg an increase or decrease in
|
|
|
|
- <literal>GrantedAuthority[]</literal>s) after the initial authentication step? Let's look at
|
|
|
|
- how that is handled now.</para>
|
|
|
|
- <para>The major authorization provider for secure objects has previously been introduced as
|
|
|
|
- <classname>AbstractSecurityInterceptor</classname>. This class needs to have access to an
|
|
|
|
- <interfacename>AuthenticationManager</interfacename>. It also has configurable settings to
|
|
|
|
- indicate whether an <interfacename>Authentication</interfacename> object should be
|
|
|
|
- re-authenticated on each secure object invocation. By default it just accepts any
|
|
|
|
- <interfacename>Authentication</interfacename> inside the
|
|
|
|
- <classname>SecurityContextHolder</classname> is authenticated if
|
|
|
|
- <literal>Authentication.isAuthenticated()</literal> returns true. This is great for
|
|
|
|
- performance, but not ideal if you want to ensure up-to-the-moment authentication validity. For
|
|
|
|
- such cases you'll probably want to set the
|
|
|
|
- <literal>AbstractSecurityInterceptor.alwaysReauthenticate</literal> property to true.</para>
|
|
|
|
- <para>You might be asking yourself, "what's this
|
|
|
|
- <interfacename>AuthenticationManager</interfacename>?". We haven't explored it before, but
|
|
|
|
- we have discussed the concept of an <classname>AuthenticationProvider</classname>. Quite
|
|
|
|
- simply, an <interfacename>AuthenticationManager</interfacename> is responsible for passing
|
|
|
|
- requests through a chain of AuthenticationProviders. It's a little like the filter chain we
|
|
|
|
- discussed earlier, although there are some differences. There is only one
|
|
|
|
- <interfacename>AuthenticationManager</interfacename> implementation shipped with Spring
|
|
|
|
- Security, so let's look at how it's configured for the example we're using in this
|
|
|
|
- chapter:</para>
|
|
|
|
- <para>
|
|
|
|
- <programlisting><![CDATA[
|
|
|
|
-<bean id="authenticationManager"
|
|
|
|
- class="org.springframework.security.authentication.ProviderManager">
|
|
|
|
- <property name="providers">
|
|
|
|
- <list>
|
|
|
|
- <ref local="daoAuthenticationProvider"/>
|
|
|
|
- <ref local="anonymousAuthenticationProvider"/>
|
|
|
|
- <ref local="rememberMeAuthenticationProvider"/>
|
|
|
|
- </list>
|
|
|
|
- </property>
|
|
|
|
-</bean>]]></programlisting>
|
|
|
|
- </para>
|
|
|
|
- <para>It's probably worth mentioning at this point that your authentication mechanisms (which
|
|
|
|
- are usually filters) are also injected with a reference to the
|
|
|
|
- <interfacename>AuthenticationManager</interfacename>. So both
|
|
|
|
- <classname>AbstractSecurityInterceptor</classname> as well as the authentication mechanisms
|
|
|
|
- will use the above <literal>ProviderManager</literal> to poll a list of
|
|
|
|
- <classname>AuthenticationProvider</classname>s.</para>
|
|
|
|
- <para>In our example we have three providers. They are tried in the order shown (which is
|
|
|
|
- implied by the use of a <literal>List</literal> instead of a <literal>Set</literal>), with
|
|
|
|
- each provider able to attempt authentication, or skip authentication by simply returning
|
|
|
|
- <literal>null</literal>. If all implementations return null, the
|
|
|
|
- <literal>ProviderManager</literal> will throw a suitable exception. If you're interested in
|
|
|
|
- learning more about chaining providers, please refer to the <literal>ProviderManager</literal>
|
|
|
|
- JavaDocs.</para>
|
|
|
|
- <para>The providers to use will sometimes be interchangeable with the authentication mechanisms,
|
|
|
|
- whilst at other times they will depend on a specific authentication mechanism. For example,
|
|
|
|
- the <literal>DaoAuthenticationProvider</literal> just needs a string-based username and
|
|
|
|
- password. Various authentication mechanisms result in the collection of a string-based
|
|
|
|
- username and password, including (but not limited to) BASIC and form authentication. Equally,
|
|
|
|
- some authentication mechanisms create an authentication request object which can only be
|
|
|
|
- interpreted by a single type of <classname>AuthenticationProvider</classname>. An example of
|
|
|
|
- this one-to-one mapping would be JA-SIG CAS, which uses the notion of a service ticket which
|
|
|
|
- can therefore only be authenticated by <literal>CasAuthenticationProvider</literal>. A further
|
|
|
|
- example of a one-to-one mapping would be the LDAP authentication mechanism, which can only be
|
|
|
|
- processed an the <literal>LdapAuthenticationProvider</literal>. The specifics of such
|
|
|
|
- relationships are detailed in the JavaDocs for each class, plus the authentication
|
|
|
|
- approach-specific chapters of this reference guide. You need not be terribly concerned about
|
|
|
|
- this implementation detail, because if you forget to register a suitable provider, you'll
|
|
|
|
- simply receive a <literal>ProviderNotFoundException</literal> when an attempt to authenticate
|
|
|
|
- is made.</para>
|
|
|
|
- <para>After configuring the correct authentication mechanisms in the
|
|
|
|
- <classname>FilterChainProxy</classname>, and ensuring that a corresponding
|
|
|
|
- <classname>AuthenticationProvider</classname> is registered in the
|
|
|
|
- <literal>ProviderManager</literal>, your last step is to configure an
|
|
|
|
- <interfacename>AuthenticationEntryPoint</interfacename>. Recall that earlier we discussed
|
|
|
|
- the role of <classname>ExceptionTranslationFilter</classname>, which is used when HTTP-based
|
|
|
|
- requests should receive back an HTTP header or HTTP redirect in order to start authentication.
|
|
|
|
- Continuing on with our earlier example:</para>
|
|
|
|
- <para>
|
|
|
|
- <programlisting><![CDATA[
|
|
|
|
-<bean id="exceptionTranslationFilter"
|
|
|
|
- class="org.springframework.security.web.access.ExceptionTranslationFilter">
|
|
|
|
- <property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
|
|
|
|
- <property name="accessDeniedHandler">
|
|
|
|
- <bean class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
|
|
|
|
- <property name="errorPage" value="/accessDenied.jsp"/>
|
|
|
|
- </bean>
|
|
|
|
- </property>
|
|
|
|
-</bean>
|
|
|
|
-
|
|
|
|
-<bean id="authenticationEntryPoint"
|
|
|
|
- class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
|
|
|
|
- <property name="loginFormUrl" value="/login.jsp"/>
|
|
|
|
- <property name="forceHttps" value="false"/>
|
|
|
|
-</bean>]]></programlisting>
|
|
|
|
- </para>
|
|
|
|
- <para>Notice that the <classname>ExceptionTranslationFilter</classname> requires two
|
|
|
|
- collaborators. The first, <literal>AccessDeniedHandlerImpl</literal>, uses a
|
|
|
|
- <literal>RequestDispatcher</literal> forward to display the specified access denied error
|
|
|
|
- page. We use a forward so that the <classname>SecurityContextHolder</classname> still contains
|
|
|
|
- details of the principal, which may be useful for display to the user (in old releases of
|
|
|
|
- Spring Security we relied upon the servlet container to handle a 403 error message, which
|
|
|
|
- lacked this useful contextual information). <literal>AccessDeniedHandlerImpl</literal> will
|
|
|
|
- also set the HTTP header to 403, which is the official error code to indicate access denied.
|
|
|
|
- In the case of the <literal>AuthentionEntryPoint</literal>, here we're setting what action we
|
|
|
|
- would like taken when an unauthenticated principal attempts to perform a protected operation.
|
|
|
|
- Because in our example we're going to be using form-based authentication, we specify
|
|
|
|
- <literal>AuthenticationProcessinFilterEntryPoint</literal> and the URL of the login page.
|
|
|
|
- Your application will usually only have one entry point, and most authentication approaches
|
|
|
|
- define their own specific <interfacename>AuthenticationEntryPoint</interfacename>. Details of
|
|
|
|
- which entry point to use for each authentication approach is discussed in the authentication
|
|
|
|
- approach-specific chapters of this reference guide.</para>
|
|
|
|
- </section>
|
|
|
|
- <section xml:id="userdetails-and-associated-types">
|
|
|
|
- <info>
|
|
|
|
- <title>UserDetails and Associated Types</title>
|
|
|
|
- </info>
|
|
|
|
- <para>As mentioned in the first part of the reference guide, most authentication providers take
|
|
|
|
- advantage of the <interfacename>UserDetails</interfacename> and
|
|
|
|
- <interfacename>UserDetailsService</interfacename> interfaces. The contract for this latter
|
|
|
|
- interface consists of a single method:</para>
|
|
|
|
- <para>
|
|
|
|
- <programlisting>
|
|
|
|
- UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException;
|
|
|
|
- </programlisting>
|
|
|
|
- </para>
|
|
|
|
- <para>The returned <interfacename>UserDetails</interfacename> is an interface that provides
|
|
|
|
- getters that guarantee non-null provision of basic authentication information such as the
|
|
|
|
- username, password, granted authorities and whether the user is enabled or disabled. Most
|
|
|
|
- authentication providers will use a <interfacename>UserDetailsService</interfacename>, even if
|
|
|
|
- the username and password are not actually used as part of the authentication decision.
|
|
|
|
- Generally such providers will be using the returned <interfacename>UserDetails</interfacename>
|
|
|
|
- object just for its <literal>GrantedAuthority[]</literal> information, because some other
|
|
|
|
- system (like LDAP or X509 or CAS etc) has undertaken the responsibility of actually validating
|
|
|
|
- the credentials.</para>
|
|
|
|
- <para>A single concrete implementation of <interfacename>UserDetails</interfacename> is provided
|
|
|
|
- with Spring Security, being the <literal>User</literal> class. Spring Security users will need
|
|
|
|
- to decide when writing their <interfacename>UserDetailsService</interfacename> what concrete
|
|
|
|
- <interfacename>UserDetails</interfacename> class to return. In most cases
|
|
|
|
- <literal>User</literal> will be used directly or subclassed, although special circumstances
|
|
|
|
- (such as object relational mappers) may require users to write their own
|
|
|
|
- <interfacename>UserDetails</interfacename> implementation from scratch. This is not such an
|
|
|
|
- unusual situation, and users should not hesitate to simply return their normal domain object
|
|
|
|
- that represents a user of the system. This is especially common given that
|
|
|
|
- <interfacename>UserDetails</interfacename> is often used to store additional
|
|
|
|
- principal-related properties (such as their telephone number and email address), so that they
|
|
|
|
- can be easily used by web views.</para>
|
|
|
|
- <para>Given <interfacename>UserDetailsService</interfacename> is so simple to implement, it
|
|
|
|
- should be easy for users to retrieve authentication information using a persistence strategy
|
|
|
|
- of their choice. Having said that, Spring Security does include a couple of useful base
|
|
|
|
- implementations, which we'll look at below.</para>
|
|
|
|
- <section xml:id="in-memory-service">
|
|
|
|
- <info>
|
|
|
|
- <title>In-Memory Authentication</title>
|
|
|
|
- </info>
|
|
|
|
- <para>Whilst it is easy to use create a custom
|
|
|
|
- <interfacename>UserDetailsService</interfacename> implementation that extracts information
|
|
|
|
- from a persistence engine of choice, many applications do not require such complexity. This
|
|
|
|
- is particularly true if you're undertaking a rapid prototype or just starting integrating
|
|
|
|
- Spring Security, when you don't really want to spend time configuring databases or writing
|
|
|
|
- <interfacename>UserDetailsService</interfacename> implementations. For this sort of
|
|
|
|
- situation, a simple option is to use the <literal>user-service</literal> element from the
|
|
|
|
- security <link xlink:href="#namespace-minimal">namespace</link>: <programlisting><![CDATA[
|
|
|
|
- <user-service id="userDetailsService">
|
|
|
|
- <user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
|
|
|
|
- <user name="bob" password="bobspassword" authorities="ROLE_USER" />
|
|
|
|
- </user-service>
|
|
|
|
- ]]>
|
|
|
|
-</programlisting> This also suppots the use of an external properties file: <programlisting><![CDATA[
|
|
|
|
- <user-service id="userDetailsService" properties="users.properties"/>
|
|
|
|
- ]]></programlisting> The properties file should contain entries in the form
|
|
|
|
- <programlisting>
|
|
|
|
- username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]
|
|
|
|
-</programlisting>
|
|
|
|
- For example
|
|
|
|
- <programlisting>
|
|
|
|
- jimi=jimispassword,ROLE_USER,ROLE_ADMIN,enabled
|
|
|
|
- bob=bobspassword,ROLE_USER,enabled
|
|
|
|
-</programlisting></para>
|
|
|
|
- </section>
|
|
|
|
- <section xml:id="jdbc-service">
|
|
|
|
- <info>
|
|
|
|
- <title>JDBC Authentication</title>
|
|
|
|
- </info>
|
|
|
|
- <para>Spring Security also includes a <interfacename>UserDetailsService</interfacename> that
|
|
|
|
- can obtain authentication information from a JDBC data source. Internally Spring JDBC is
|
|
|
|
- used, so it avoids the complexity of a fully-featured object relational mapper (ORM) just to
|
|
|
|
- store user details. If your application does use an ORM tool, you might prefer to write a
|
|
|
|
- custom <interfacename>UserDetailsService</interfacename> to reuse the mapping files you've
|
|
|
|
- probably already created. Returning to <literal>JdbcDaoImpl</literal>, an example
|
|
|
|
- configuration is shown below:</para>
|
|
|
|
- <para>
|
|
|
|
- <programlisting>
|
|
|
|
-<![CDATA[
|
|
|
|
-<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
|
|
|
|
- <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
|
|
|
|
- <property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/>
|
|
|
|
- <property name="username" value="sa"/>
|
|
|
|
- <property name="password" value=""/>
|
|
|
|
-</bean>
|
|
|
|
-
|
|
|
|
-<bean id="userDetailsService" class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
|
|
|
|
- <property name="dataSource" ref="dataSource"/>
|
|
|
|
-</bean> ]]> </programlisting>
|
|
|
|
- </para>
|
|
|
|
- <para>You can use different relational database management systems by modifying the
|
|
|
|
- <literal>DriverManagerDataSource</literal> shown above. You can also use a global data
|
|
|
|
- source obtained from JNDI, as per normal Spring options. </para>
|
|
|
|
- <section xml:id="jdbc-default-schema">
|
|
|
|
- <title>Default User Database Schema</title>
|
|
|
|
- <para> Irrespective of the database you are using and how a <literal>DataSource</literal> is
|
|
|
|
- obtained, a standard schema must be in place. The DDL for an HSQL database instance would
|
|
|
|
- be:
|
|
|
|
- <programlisting>
|
|
|
|
- CREATE TABLE users (
|
|
|
|
- username VARCHAR(50) NOT NULL PRIMARY KEY,
|
|
|
|
- password VARCHAR(50) NOT NULL,
|
|
|
|
- enabled BIT NOT NULL
|
|
|
|
- );
|
|
|
|
-
|
|
|
|
- CREATE TABLE authorities (
|
|
|
|
- username VARCHAR(50) NOT NULL,
|
|
|
|
- authority VARCHAR(50) NOT NULL
|
|
|
|
- );
|
|
|
|
-
|
|
|
|
- ALTER TABLE authorities ADD CONSTRAINT fk_authorities_users \
|
|
|
|
- foreign key (username) REFERENCES users(username);
|
|
|
|
-</programlisting></para>
|
|
|
|
- <para>If the default schema is unsuitable for your needs, <literal>JdbcDaoImpl</literal>
|
|
|
|
- provides properties that allow customisation of the SQL statements. Please refer to the
|
|
|
|
- JavaDocs for details, but note that the class is not intended for complex custom
|
|
|
|
- subclasses. If you have a complex schema or would like a custom
|
|
|
|
- <interfacename>UserDetails</interfacename> implementation returned, you'd be better off
|
|
|
|
- writing your own <interfacename>UserDetailsService</interfacename>. The base
|
|
|
|
- implementation provided with Spring Security is intended for typical situations, rather
|
|
|
|
- than catering for all possible requirements.</para>
|
|
|
|
- </section>
|
|
|
|
- </section>
|
|
|
|
- </section>
|
|
|
|
- <section xml:id="concurrent-sessions">
|
|
|
|
- <info>
|
|
|
|
- <title>Concurrent Session Handling</title>
|
|
|
|
- </info>
|
|
|
|
- <para>Spring Security is able to prevent a principal from concurrently authenticating to the
|
|
|
|
- same application more than a specified number of times. Many ISVs take advantage of this to
|
|
|
|
- enforce licensing, whilst network administrators like this feature because it helps prevent
|
|
|
|
- people from sharing login names. You can, for example, stop user "Batman" from logging onto
|
|
|
|
- the web application from two different sessions.</para>
|
|
|
|
- <para>To use concurrent session support, you'll need to add the following to
|
|
|
|
- <literal>web.xml</literal>: <programlisting><![CDATA[
|
|
|
|
- <listener>
|
|
|
|
- <listener-class>
|
|
|
|
- org.springframework.security.web.session.HttpSessionEventPublisher
|
|
|
|
- </listener-class>
|
|
|
|
- </listener> ]]>
|
|
|
|
- </programlisting></para>
|
|
|
|
- <para>In addition, you will need to add the
|
|
|
|
- <literal>org.springframework.security.web.authentication.concurrent.ConcurrentSessionFilter</literal>
|
|
|
|
- to your <classname>FilterChainProxy</classname>. The
|
|
|
|
- <classname>ConcurrentSessionFilter</classname> requires two properties,
|
|
|
|
- <literal>sessionRegistry</literal>, which generally points to an instance of
|
|
|
|
- <literal>SessionRegistryImpl</literal>, and <literal>expiredUrl</literal>, which points to
|
|
|
|
- the page to display when a session has expired.</para>
|
|
|
|
- <para>The <literal>web.xml</literal>
|
|
|
|
- <literal>HttpSessionEventPublisher</literal> causes an <literal>ApplicationEvent</literal> to
|
|
|
|
- be published to the Spring <literal>ApplicationContext</literal> every time a
|
|
|
|
- <literal>HttpSession</literal> commences or terminates. This is critical, as it allows the
|
|
|
|
- <classname>SessionRegistryImpl</classname> to be notified when a session ends.</para>
|
|
|
|
- <para>You will also need to wire up the <classname>ConcurrentSessionControllerImpl</classname>
|
|
|
|
- and refer to it from your <literal>ProviderManager</literal> bean:</para>
|
|
|
|
- <para>
|
|
|
|
- <programlisting><![CDATA[
|
|
|
|
-<bean id="authenticationManager"
|
|
|
|
- class="org.springframework.security.authentication.ProviderManager">
|
|
|
|
- <property name="providers">
|
|
|
|
- <!-- your providers go here -->
|
|
|
|
- </property>
|
|
|
|
- <property name="sessionController" ref="concurrentSessionController"/>
|
|
|
|
-</bean>
|
|
|
|
-
|
|
|
|
-<bean id="concurrentSessionController" class=
|
|
|
|
- "org.springframework.security.authentication.concurrent.ConcurrentSessionControllerImpl">
|
|
|
|
- <property name="maximumSessions" value="1"/>
|
|
|
|
- <property name="sessionRegistry">
|
|
|
|
- <bean
|
|
|
|
- class="org.springframework.security.authentication.concurrent.SessionRegistryImpl"/>
|
|
|
|
- <property>
|
|
|
|
-</bean>
|
|
|
|
-]]></programlisting>
|
|
|
|
- </para>
|
|
|
|
- </section>
|
|
|
|
- <section xml:id="authentication-taglibs">
|
|
|
|
- <info>
|
|
|
|
- <title>Authentication Tag Libraries</title>
|
|
|
|
- </info>
|
|
|
|
- <para><literal>AuthenticationTag</literal> is used to simply output a property of the current
|
|
|
|
- <interfacename>Authentication</interfacename> object to the web page.</para>
|
|
|
|
- <para>The following JSP fragment illustrates how to use the
|
|
|
|
- <literal>AuthenticationTag</literal>:</para>
|
|
|
|
- <para>
|
|
|
|
- <programlisting><security:authentication property="principal.username"/></programlisting>
|
|
|
|
- </para>
|
|
|
|
- <para>This tag would cause the principal's name to be output. Here we are assuming the
|
|
|
|
- <literal>Authentication.getPrincipal()</literal> is a
|
|
|
|
- <interfacename>UserDetails</interfacename> object, which is generally the case when using
|
|
|
|
- one of Spring Security's stadard <classname>AuthenticationProvider</classname>
|
|
|
|
- implementations.</para>
|
|
|
|
- </section>
|
|
|
|
-</chapter>
|
|
|