2014-03-04 3 views
1

웹 응용 프로그램에서 Spring 보안 3.2.0을 사용하고 있습니다.스프링 보안 - 다중 인증 제공 업체의 remember-me 인증

나는 데이터베이스에 자격 증명을 저장 한 사용자와 구성 파일에 저장된 자격 증명을 가진 관리자라는 두 가지 보안 역할이 있습니다.

remember-me 인증을 사용할 때까지 제대로 작동합니다. 여기 내 security.xml 설정입니다 :

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

관리자로 로그인하면 잘됩니다. 성공적으로 인증하지만 경우

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) 

를 내가 내 응용 프로그램 인덱스 페이지를 열 경우는 "사용자 1"로 로그인 같습니다

가 나는 j_spring_security_check에 예외가 발생 사용자로 로그인 할 때.

jdbcUserSrv에 대한 remember-me 구성이 adminSrv 구성보다 앞서면 "admin"사용자에게 오류가 나타납니다.

현재 구성은 remember-me 옵션없이 정상적으로 작동하지만 사용하도록 설정해야합니다.

이러한 오류를 방지하는 방법을 알려주십시오.

+0

AFAIK를, 봄은 당신이 기억-나를 UserDetailsService의 빈을 기대하는이 필요합니다. 스프링 박사님, http://docs.spring.io/spring-security/site/docs/3.0.x/reference/remember-me.html – Lucky

답변

2

두 개의 기억 장치 요소가 있으면 단순히 서로 무시하는 것입니다. UserDetailsService 인스턴스가 여러 개 있으면 문제가 발생할 수 있습니다. 예를 들어 사용자와 관련된 데이터가 있다고 가정합니다. admin이라는 사용자가 메모리와 jdbc UserDetailsService 인스턴스에 모두 존재할 경우 데이터가 속한 admin 사용자를 어떻게 알 수 있습니까? 이러한 이유로 단일 UserDetailsService를 사용하는 것이 가장 좋습니다.

또는 여러 UserDetailsService 인스턴스에 위임하는 UserDetailsService를 만들 수 있습니다. 예를 들어 :

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; 
    } 
} 

은 다음 당신은 기억-나를 대신 사용 할 수 있습니다 :

<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> 
+0

답장을 보내 주셔서 감사합니다. 내 자신의 UserDetailsService를 구현하기로 결정했지만 솔루션 또한 매우 유용합니다. – Nailgun