春季安全 - 记住,我有多个身份验证提供身份验证 [英] Spring security - remember-me authentication with multiple authentication providers
问题描述
我使用Spring Security的3.2.0在我的Web应用程序。
I'm using Spring security 3.2.0 in my web application.
我有两个安全角色:与存储在数据库中的凭据用户和管理员枝条保存在配置文件中的凭据。
I have two security roles: users with the credentials stored in database and administrators withe credentials stored in configuration file.
直到我打开记得,我验证它工作正常。这里是我的 security.xml文件
配置:
It works fine until I turn on remember-me authentication. Here is my security.xml
config:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<security:global-method-security secured-annotations="enabled"/>
<security:http auto-config="true">
<security:remember-me key="myAppKey" user-service-ref="adminSrv"/>
<security:remember-me key="myAppKey" user-service-ref="jdbcUserSrv"/>
<security:form-login login-page="/login" default-target-url="/"
authentication-failure-url="/loginfailed" />
<security:logout logout-success-url="/logout"/>
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:jdbc-user-service data-source-ref="dataSource" id="jdbcUserSrv"
users-by-username-query="/* SQL query */"
authorities-by-username-query="/* Another SQL query */"
/>
</security:authentication-provider>
<security:authentication-provider>
<security:user-service id="adminSrv">
<security:user name="admin" authorities="ROLE_ADMIN" password="passwd"/>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
当我以管理员身份登录它去罚款。
When I log in as administrator it goes fine.
当我尝试以用户身份登录它抛出异常的j_spring_security_check:
When I try to log in as user it throws exception on j_spring_security_check:
HTTP ERROR 500
Problem accessing /mercury/j_spring_security_check. Reason:
user1
Caused by:
org.springframework.security.core.userdetails.UsernameNotFoundException: user1
at org.springframework.security.provisioning.InMemoryUserDetailsManager.loadUserByUsername(InMemoryUserDetailsManager.java:113)
at org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices.onLoginSuccess(TokenBasedRememberMeServices.java:178)
at org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices.loginSuccess(AbstractRememberMeServices.java:262)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.successfulAuthentication(AbstractAuthenticationProcessingFilter.java:324)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.successfulAuthentication(AbstractAuthenticationProcessingFilter.java:298)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:235)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)
at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:326)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:943)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:756)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:410)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
但是,如果它成功通过验证,如果我打开我的应用程序的索引页它显示登录为USER1。
However if it is authenticated successfully and if I open my application index page it is shown logged in as "user1".
如果记得,我
配置为jdbcUserSrv那张配置为adminSrv出现admin用户则错误之前。
If remember-me
config for jdbcUserSrv goes before the config for adminSrv then the error appears for "admin" user.
当前配置工作正常,而不记得,我
的选择,但我需要他们启用。
Current configuration works fine without the remember-me
options but I need them to be enabled.
请指点我如何避免这些错误。
Please advice me how to avoid these errors.
推荐答案
有两个remember-me的元素被简单地覆盖彼此。拥有多个的UserDetailsService实例可以让你陷入困境了。例如,我想你可能有你的用户相关的数据。如果双方在记忆和JDBC的UserDetailsService实例中存在一个名为admin的用户的话,你怎么知道哪个管理用户的数据属于?由于这个原因,很可能最好使用单个的UserDetailsService
Having two remember-me elements is simply overriding one another. Having multiple UserDetailsService instances can get you into trouble too. For example, I assume you likely have data associated with your users. If a user named admin exists in both the in memory and the jdbc UserDetailsService instances, then how do you know which admin user the data belongs to? For this reason, it is likely best to use a single UserDetailsService.
另外,您可以创建一个UserDetailsService中委托给多个的UserDetailsService实例。例如:
Alternatively you can create a UserDetailsService that delegates to multiple UserDetailsService instances. For example:
public class DelegatingUserDetailsService implements UserDetailsService {
private final List<UserDetailsService> userDetailsServices;
public DelegatingUserDetailsService(
List<UserDetailsService> userDetailsServices) {
this.userDetailsServices = userDetailsServices;
}
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
RuntimeException last = null;
for(UserDetailsService uds : userDetailsServices) {
try {
return uds.loadUserByUsername(username);
} catch(RuntimeException error) {
last = error;
}
}
throw last;
}
}
然后您可以记住,我用它来代替:
Then you can have remember-me use it instead:
<bean id="delegateUds" class="DelegatingUserDetailsService">
<constructor-arg>
<list>
<ref bean="jdbcUserSrv"/>
<ref bean="adminSrv"/>
</list>
</constructor-arg>
</bean>
<security:http auto-config="true">
<security:remember-me key="myAppKey" user-service-ref="delegateUds"/>
<security:form-login login-page="/login" default-target-url="/"
authentication-failure-url="/loginfailed" />
<security:logout logout-success-url="/logout"/>
</security:http>
这篇关于春季安全 - 记住,我有多个身份验证提供身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!