2014-03-13 6 views
5

스프링 보안 v3.1.4를 사용 중입니다. 내가 원하는 것은 관리자가 일반 사용자를 로그 아웃 (세션을 무효화) 할 수있게하는 것입니다. 사용자는 주어진 시간에 한 번만 로그인 할 수 있지만 로그 아웃하는 것을 잊어 버린 경우 다른 위치에서 로그인하려고하면 로그인 할 수 없으므로 로그인 할 수 없습니다. 관리자 및 관리자는 이전에 로그인 한 모든 세션을 무효화합니다 (단 하나만있는 경우).스프링 보안을 사용하여 프로그래밍 방식으로 사용자를 로그 아웃하는 방법

내 web.xml에 다음 정의가 있습니다.

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

내 봄 보안 xml에 다음 정의가 있습니다.

<session-management invalid-session-url="/home"> 
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" session-registry-ref="sessionRegistry"/> 
</session-management> 
<beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/> 

그러면 로그 아웃을 수행하는 나머지 컨트롤러가 있습니다.

@Controller 
@RequestMapping("/api/admin") 
public class RestAdminController { 
static final Set<SimpleGrantedAuthority> AUTHS = new HashSet<>(); 
static { 
    AUTHS.add(new SimpleGrantedAuthority("ROLE_USER")); 
} 

@Autowired 
private SessionRegistry sessionRegistry; 

@RequestMapping("/user/logout"); 
public @ResponseBody String logout(@RequestBody Account account) { 
    User user = new User(account.getUsername(), "", AUTHS); 
    List<SessionInformation> infos = sessionRegistry.getAllSessions(u, false); 

    for(SessionInformation info : infos) { 
    info.expireNow(); //expire the session 
    sessionRegistry.removeSessionInformation(info.getSessionId()); //remove session 
    } 

    return "ok"; 
} 
} 

이 코드는 "동일한"컴퓨터에서 테스트 할 때 작동합니다. 사용자 USER_A와 관리자 ADMIN_A가 있다고 가정 해 보겠습니다.

  • USER_A는 APP에 로그인하기 위해 크롬을 사용합니다.
  • USER_A는 firefox를 사용하여 APP에 로그인합니다. 사용자는 한 번에 1 개의 로그인 세션 만 가질 수 있으므로 거부됩니다.
  • ADMIN_A는 들어오고 나머지 USER_A의 세션을 모두 "걷어차 기"위해 위와 같은 코드를 호출합니다.
  • USER_A는 이제 firefox를 사용하여 APP에 로그인 할 수 있습니다.

그러나 이제 USER_A는 크롬에 한 번, 파이어 폭스에 한 번 두 번 로그인됩니다.

  • 크롬에서 USER_A (첫 번째 로그인)의 (스프링 보안으로 보호 된) 페이지를 새로 고침해도 강제로 (로그인 페이지로) 리디렉션되지 않습니다.
  • firefox (두 번째 로그인)에서 USER_A에 대한 보호 된 페이지를 새로 고치면 강제로 리디렉션되지 않습니다.

USER_A의 첫 번째/이전 로그인 세션을 완전히 무효화/파괴하는 방법에 대한 아이디어가 있습니다. 보호 된 페이지에 액세스하려고 시도하면 봄 보안 팀에서 "이 사람 세션이 유효하지 않거나 만료되었습니다. 로그인 페이지 "?

어떤 도움을 주시면 감사하겠습니다. 감사.

답변

10

거의 다 알았지 만 문제는 정보를 기꺼이 SessionRegistry에서 제거하는 것입니다. ConcurrentSessionFilter은 사용자가 요청할 때 현재 세션에 대한 검사를 수행하며,이 시점에서 만료 된 세션을 로그 아웃하고 무효화합니다. 해당 세션의 정보를 이미 제거 했으므로 세션을 찾지 못해 아무 것도하지 않습니다.

선을 제거해보십시오 :

sessionRegistry.removeSessionInformation(info.getSessionId()); 
+0

덕분에 그 줄을 제거하면 해당 부작용이 제거되었습니다.그러나 스프링 보호 페이지를 새로 고칠 때 "이 세션은 만료되었습니다 (아마도 동일한 사용자로 여러 동시 로그인이 시도 되었기 때문에)."라는 메시지가 나타납니다. 리디렉션이 정확하면/home으로 리디렉션되지만/home의 내용을 표시하는 대신 표시 할 실제 내용을 가져 오기 위해 새로 고쳐야하는 해당 메시지를 표시합니다. 이 메시지의 출처는 어디입니까? JEE 컨테이너처럼 보이지 않습니다. 어떻게 사용자 정의 할 수 있습니까? –

+0

좋아, 그래서 내 followup에 대한 답변을 이미 가지고있다. 동시성 제어에서 만료 된 URL을 제어 할 수 있습니다. –

+0

오른쪽. [네임 스페이스 부록] (http://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#nsa-concurrency-control)은 구성을 찾기에 좋은 장소입니다. 속성. 또한, 그들은 괜찮은 XML 편집기에 표시됩니다. –

관련 문제