2012-03-28 3 views
22

저는 스프링 보안을 사용하는 OpenID에 의한 인증을 통해 애플리케이션을 수행하고 있습니다. 사용자가 로그인하면 일부 권한이 세션에로드됩니다.스프링 보안을 사용하여 사용자 업데이트시 권한을 다시로드하는 방법

다른 사용자의 권한 (권한 취소, 역할 추가)을 수정할 수있는 권한을 가진 사용자가 있습니다. 내 질문은 동적으로 사용자 세션 권한을 변경하는 방법입니다. (다른 사용자 세션을 변경하려고하므로 SecurityContextHolder을 사용할 수 없습니다.)

간단한 방법 : 사용자 세션을 무효화하는 방법은 무엇입니까? 더 나은 방법 : 새 권한으로 사용자 세션을 새로 고치지 만 방법은 무엇입니까?

답변

6

요점 - 사용자 SecurityContext에 액세스 할 수 있어야합니다.

당신은 서블릿 환경에있는 당신의 securityContextPersistenceFiltersecurityContextRepositoryHttpSession를 사용하는 경우, 그것은 봄의 SessionRegistry 수행 할 수 있습니다. 사용자에게 다시 인증하도록하려면 (무의미한 사용 권한 해지보다 좋음) 그의 HttpSession을 무효화합니다. 당신이 스레드 로컬 securityContextRepository 사용하는 경우

<listener> 
    <listener-class> 
     org.springframework.security.web.session.HttpSessionEventPublisher 
    </listener-class> 
</listener> 

을 web.xml에 할 HttpSessionEventPublisher를 추가하는 것을 잊지 마세요, 당신은 SecurityContext의 레지스트리를 관리 할 수 ​​springSecurityFilterChain에 사용자 정의 필터를 추가해야합니다. 이렇게하려면 일반 콩 springSecurityFilterChain 구성 (security 네임 스페이스 바로 가기 없음)을 사용해야합니다. 사용자 정의 필터가있는 빈 bean 설정을 사용하면 인증 및 권한 부여를 완전히 제어 할 수 있습니다.

일부 링크, 그들은 정확히 문제 (NO 오픈 ID)를 해결하지 않지만 유용 할 수 있습니다 : 서블릿 환경

  • it's plain-bean spring config 작업 예를
  • real life plain-bean spring config for X.509 auth에 대한

    • NIH session registry, 당신이 시작할 수 있습니다 X.509 대신 OpenID를 사용하도록 수정하십시오.
  • 7

    감사합니다. SessionRegistry을 사용하면 getAllPrincipals()을 사용하여 사용자를 세션의 현재 활성 사용자와 비교할 수 있습니다. 세션이 존재하는 경우 expireNow() (SessionInformation)을 사용하여 세션을 무효화하여 강제로 재 인증 할 수 있습니다.

    그러나 securityContextPersistenceFilter의 유용성을 이해하지 못합니까?

    편집 : 동적으로 로그 아웃 물론 로그인 할 필요없이, (이들은 어떤 이유 변경된 경우) 사용자의 권한으로 로그인 업데이트해야하는 경우

    // user object = User currently updated 
    // invalidate user session 
    List<Object> loggedUsers = sessionRegistry.getAllPrincipals(); 
    for (Object principal : loggedUsers) { 
        if(principal instanceof User) { 
         final User loggedUser = (User) principal; 
         if(user.getUsername().equals(loggedUser.getUsername())) { 
          List<SessionInformation> sessionsInfo = sessionRegistry.getAllSessions(principal, false); 
          if(null != sessionsInfo && sessionsInfo.size() > 0) { 
           for (SessionInformation sessionInformation : sessionsInfo) { 
            LOGGER.info("Exprire now :" + sessionInformation.getSessionId()); 
            sessionInformation.expireNow(); 
            sessionRegistry.removeSessionInformation(sessionInformation.getSessionId()); 
            // User is not forced to re-logging 
           } 
          } 
         } 
        } 
    } 
    
    +0

    '서블릿 환경에서'HttpSession'에'SecurityContext'를 넣어 것입니다 기본적으로 securityContextPersistenceFilter'. 이미 out-of-the-box 스프링 SessionRegistry를 사용하고 있으므로이 필터를 사용자 정의 할 필요가 없습니다. – alexkasko

    +0

    나는 서블릿 환경에 있는데, securityContextPersistenceFilter를 커스터마이즈하는 것이 유용할까요? – Aure77

    +0

    다른 사례가 가능합니다. 'HttpSession'은 사용할 수없고 스레드 로컬 저장을 원하지 않습니다. 그래서 당신은'securityContextRepository'의 당신 자신의 구현을 사용할 수 있습니다. 'HttpSession' 저장소가 당신의 요구에 맞으면, 유용성이 없다. – alexkasko

    22

    , 당신은 단지 필요 SecurityContextHolder에서 Authentication 개체 (보안 토큰)를 재설정하십시오.

    예 :

    Authentication auth = SecurityContextHolder.getContext().getAuthentication(); 
    
    List<GrantedAuthority> updatedAuthorities = new ArrayList<>(auth.getAuthorities()); 
    updatedAuthorities.add(...); //add your role here [e.g., new SimpleGrantedAuthority("ROLE_NEW_ROLE")] 
    
    Authentication newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(), auth.getCredentials(), updatedAuthorities); 
    
    SecurityContextHolder.getContext().setAuthentication(newAuth); 
    
    +5

    글쎄, 거의 나를 위해 일했다. 이 "auth"변수는 로그인 한 사용자 (즉, 나)와 관계가 있습니다. "x"로 로그인되어 있고 "y"권한을 취소하고 싶다면 특정 사용자로부터 인증의 객체를 얻으려면 어떻게해야합니까? – Paulo

    관련 문제