I have a custom-authentication-provider defined in my Spring Security configuration. This class implements AuthenticationProvider, and I can successfully log in using the form defined on my page. The issue is I want to call this class not just on the login page, but from the registration page as well.
The registration page uses a different command class and collects more information than the login form. Right now, when the user registers, I call the appropriate controller, add the record to the database and they can then log in but they aren't logged in automatically. As they've just given me their user name/password on the registration page, can I then pass this to the custom AuthenticationProvider class so they are also logged in?
I've tried creating an org.springframework.securi开发者_如何学运维ty.Authentication class in the registration controller and calling the authenticate method on my customer AuthenticationProvider class, and this doesn't error out, but the user isn't logged in. Do I have to call a method higher in the Spring Security filter chain to accomplish this? Should I redirect the controller to the j_spring_security_check URL? If so, how would I pass the username/password?
You need to put the result of AuthenticationProvider.authenticate()
into SecurityContext
(obtained from SecurityContextHolder
).
Also be aware of AuthenticationSuccessEvent
- if your application rely on this event (some Spring Security features may use it, too), you should publish it (you can obtain the default AuthenticationEventPublisher
via autowiring). It may be useful to wrap your authentication provider with ProviderManager
, it publishes the event automatically using the given publisher.
The problem you are having is that although you have successfully authenticated the user you have not stored the result of this authentication in the user's SecurityContext
. In a web application this is a ThreadLocal
object which the SecurityContextPersistenceFilter
will use to store the user's credentials in the HTTPSession
You should also avoid authenticating directly with your custom authentication provider if you can. Your xml configuration should contain an AuthenticationManager
which your custom authentication provider has been wired into. For example,
<bean id="customAuthenticationProvider"
class="com.foo.CustomAuthenticationProvider">
<property name="accountService" ref="accountService"/>
</bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="customAuthenticationProvider"/>
</security:authentication-manager>
If you wire the authenticationManager
into your registration service and authenticate using that it will additionally,
- allow you to swap in/out additional authentication providers at later points
- publish the authentication result to other parts of the Spring Security framework (eg success/failure Exception handling code)
Our registration service does this as follows
final UsernamePasswordAuthenticationToken authRequest = new
UsernamePasswordAuthenticationToken(username, password);
final Authentication authentication =
authenticationManager.authenticate(authRequest);
SecurityContextHolder.getContext().setAuthentication(authentication);
We also optionally store the authentication result at this point in a remember-me cookie using the onLoginSuccess()
method of TokenBasedRememberMeServices
.
精彩评论