Spring Security(二十):6.2.3 Form and Basic Login Options
You might be wondering where the login form came from when you were prompted to log in, since we made no mention of any HTML files or JSPs. In fact, since we didn’t explicitly set a URL for the login page, Spring Security generates one automatically, based on the features that are enabled and using standard values for the URL which processes the submitted login, the default target URL the user will be sent to after logging in and so on. However, the namespace offers plenty of support to allow you to customize these options. For example, if you want to supply your own login page, you could use:
<http> <intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/> <intercept-url pattern="/**" access="ROLE_USER" /> <form-login login-page='/login.jsp'/> </http>
Also note that we’ve added an extra intercept-url
element to say that any requests for the login page should be available to anonymous users [3] and also the AuthenticatedVoter class for more details on how the value IS_AUTHENTICATED_ANONYMOUSLY
is processed.]. Otherwise the request would be matched by the pattern /** and it wouldn’t be possible to access the login page itself! This is a common configuration error and will result in an infinite loop in the application. Spring Security will emit a warning in the log if your login page appears to be secured. It is also possible to have all requests matching a particular pattern bypass the security filter chain completely, by defining a separate http
element for the pattern like this:
<http pattern="/css/**" security="none"/> <http pattern="/login.jsp*" security="none"/> <http use-expressions="false"> <intercept-url pattern="/**" access="ROLE_USER" /> <form-login login-page='/login.jsp'/> </http>
From Spring Security 3.1 it is now possible to use multiple http
elements to define separate security filter chain configurations for different request patterns. If the pattern
attribute is omitted from an http
element, it matches all requests. Creating an unsecured pattern is a simple example of this syntax, where the pattern is mapped to an empty filter chain [4]. We’ll look at this new syntax in more detail in the chapter on the Security Filter Chain.
requires-channel
, so you will not be able to access information on the current user or call secured methods during the request. Use access='IS_AUTHENTICATED_ANONYMOUSLY'
as an alternative if you still want the security filter chain to be applied.<http use-expressions="false"> <intercept-url pattern="/**" access="ROLE_USER" /> <http-basic /> </http>
Basic authentication will then take precedence and will be used to prompt for a login when a user attempts to access a protected resource. Form login is still available in this configuration if you wish to use it, for example through a login form embedded in another web page.
<http use-expressions="false"> <intercept-url pattern="/**" access="ROLE_USER" /> <http-basic /> </http>
Basic authentication will then take precedence and will be used to prompt for a login when a user attempts to access a protected resource. Form login is still available in this configuration if you wish to use it, for example through a login form embedded in another web page.
Setting a Default Post-Login Destination(设置默认的登录后目的地)
If a form login isn’t prompted by an attempt to access a protected resource, the default-target-url
option comes into play. This is the URL the user will be taken to after successfully logging in, and defaults to "/". You can also configure things so that the user always ends up at this page (regardless of whether the login was "on-demand" or they explicitly chose to log in) by setting the always-use-default-target
attribute to "true". This is useful if your application always requires that the user starts at a "home" page, for example:
<http pattern="/login.htm*" security="none"/> <http use-expressions="false"> <intercept-url pattern='/**' access='ROLE_USER' /> <form-login login-page='/login.htm' default-target-url='/home.htm' always-use-default-target='true' /> </http>
For even more control over the destination, you can use the authentication-success-handler-ref
attribute as an alternative to default-target-url
. The referenced bean should be an instance of AuthenticationSuccessHandler
. You’ll find more on this in the Core Filters chapter and also in the namespace appendix, as well as information on how to customize the flow when authentication fails.
6.2.4 Logout Handling
The logout
element adds support for logging out by navigating to a particular URL. The default logout URL is /logout
, but you can set it to something else using the logout-url
attribute. More information on other available attributes may be found in the namespace appendix.
6.2.5 Using other Authentication Providers(使用其他身份验证提供程序)
In practice you will need a more scalable source of user information than a few names added to the application context file. Most likely you will want to store your user information in something like a database or an LDAP server. LDAP namespace configuration is dealt with in the LDAP chapter, so we won’t cover it here. If you have a custom implementation of Spring Security’s UserDetailsService
, called "myUserDetailsService" in your application context, then you can authenticate against this using
<authentication-manager> <authentication-provider user-service-ref='myUserDetailsService'/> </authentication-manager>
If you want to use a database, then you can use
<authentication-manager> <authentication-provider> <jdbc-user-service data-source-ref="securityDataSource"/> </authentication-provider> </authentication-manager>
Where "securityDataSource" is the name of a DataSource
bean in the application context, pointing at a database containing the standard Spring Security user data tables. Alternatively, you could configure a Spring Security JdbcDaoImpl
bean and point at that using the user-service-ref
attribute:
<authentication-manager> <authentication-provider user-service-ref='myUserDetailsService'/> </authentication-manager> <beans:bean id="myUserDetailsService" class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl"> <beans:property name="dataSource" ref="dataSource"/> </beans:bean>
You can also use standard AuthenticationProvider
beans as follows
<authentication-manager> <authentication-provider ref='myAuthenticationProvider'/> </authentication-manager>
where myAuthenticationProvider
is the name of a bean in your application context which implements AuthenticationProvider
. You can use multiple authentication-provider
elements, in which case the providers will be queried in the order they are declared. See Section 6.6, “The Authentication Manager and the Namespace” for more on information on how the Spring Security AuthenticationManager
is configured using the namespace.
Adding a Password Encoder(添加密码编码器)
Passwords should always be encoded using a secure hashing algorithm designed for the purpose (not a standard algorithm like SHA or MD5). This is supported by the <password-encoder>
element. With bcrypt encoded passwords, the original authentication provider configuration would look like this:
<beans:bean name="bcryptEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/> <authentication-manager> <authentication-provider> <password-encoder ref="bcryptEncoder"/> <user-service> <user name="jimi" password="d7e6351eaa13189a5a3641bab846c8e8c69ba39f" authorities="ROLE_USER, ROLE_ADMIN" /> <user name="bob" password="4e7421b1b8765d8f9406d87e7cc6aa784c4ab97f" authorities="ROLE_USER" /> </user-service> </authentication-provider> </authentication-manager>
bcrypt is a good choice for most cases, unless you have a legacy system which forces you to use a different algorithm. If you are using a simple hashing algorithm or, even worse, storing plain text passwords, then you should consider migrating to a more secure option like bcrypt.