2013-04-11 6 views
5

사용자가 로그 아웃 할 때 쿠키 JSESSIONID를 삭제해야합니다. 내 보안 설정에 다음 설정을 추가 한하려면 :SpringSecurity : JSESSIONID를 삭제하지 못했습니다.

<http> 
    <form-login login-page="/login*" authentication-failure-url="/login?try_again" /> 
    <http-basic /> 
    <logout logout-url="/logout" delete-cookies="JSESSIONID" /> 
    <session-management invalid-session-url="/timeout" /> 

    <intercept-url pattern="/login*" access="IS_AUTHENTICATED_ANONYMOUSLY" /> 

    ... 

</http> 

그러나 대신 삭제되는 쿠키는 중복되었다한다 : 그래서 그것을

Old cookie

New cookie

브라우저를 "/ timeout"URL로 리디렉션합니다.

내가 크롬 웹 브라우저의 개발자 도구를 사용하여 무슨 일이 일어나고 있는지 추적했는데, 나는이 쿠키는이 응답 헤더로 설정하는 것을 발견

:

Set-Cookie:JSESSIONID=CFF85EA743724F23FDA0317A75CFAD44; Path=/website/; HttpOnly 

그리고이 응답 헤더 삭제합니다

Set-Cookie:JSESSIONID=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/website 

잘 모르겠지만 이유는이 헤더의 "경로"필드에있는 것처럼 보입니다. 첫 번째 페이지는 "/ website /"를 가리키고 두 번째 페이지는 "/웹 사이트 ".

설명 된 문제의 원인입니까? 이유가 아닌 경우 (또는 유일한 이유가 아닌 경우), 다른 이유는 무엇입니까? 이 문제를 어떻게 해결해야합니까?

+0

참조 http://static.springsource.org/spring-security/site/docs/3.2.x/reference/springsecurity-single.html#ns-session- mgmt (3.3.3 절) ... 유감스럽게도 모든 서블릿 컨테이너에서 작동한다는 보장은 없으므로 환경에서 테스트해야합니다. 관련 각주도 참조하십시오. – Ritesh

답변

6

이렇게 JSESSIONID 쿠키를 명시 적으로 삭제하지 않아도됩니다. Spring Security에 의해 관리되는 것이 아니라 서블릿 컨테이너에 의해 관리됩니다. 스프링 시큐리티는 기본적으로 로그 아웃시 http 세션을 무효화 할 것이고, 그 결과 서블릿 컨테이너가 JSESSIONID 쿠키를 제거하게됩니다.

로그 아웃을 삭제하는 방법
<security:logout invalidate-session="true" logout-success-url="/myapp/auth/login" logout-url="/myapp/auth/logout" /> 
+2

http://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#ns-session-mgmt는 세션 관리 태그를 다시 사용하면 명시 적으로 쿠키를 삭제하십시오. – Richie

2

이것은 내가 세션을 무효화하는 방법입니다 당신이 로그 아웃을 구현하는 방법에 그 코드를 삽입 :

HttpSession session = request.getSession(false); 
    if (session != null) { 
     session.invalidate(); 
    } 

에서 Invalidated 세션 쿠키가 무효가됩니다.

하지만 로그 아웃하지 않고 브라우저를 닫을 때 브라우저가 열리면 JSESSIONID 쿠키가 남아 있고 사용자가 시스템에 들어갈 수 있다는 것을 알았습니다.

이 문제를 해결하기 위해 로그인시 세션을 무효화하는 필터를 만들었습니다. 그러면 새 세션이 만들어지고 로그인이 처음부터 수행됩니다. SecurityContextLogoutHandler 전화 session.invalidate()JSESSIONID이 해제되지 않을 경우에도 몇 가지 이유로 내 경우

@WebFilter(urlPatterns = {"/login/*"}, description = "sessionKiller", filterName="sessionKiller") 
public class SessionKillerFilter implements Filter{ 

    @Override 
    public void init(FilterConfig arg0) throws ServletException {} 

    @Override 
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { 
     //kill older session and create new one on explicit login 
     //this is to prevent user to login 2-ce 
     //also this is prevention of re-connect on cookie base, when browser closed and then open 
     HttpServletRequest request = (HttpServletRequest)req; 
     HttpSession session = request.getSession(false); 
     if(session!=null){ 
      session.invalidate();//old session invalidated 
     } 
     request.getSession(true);//new session created 

     chain.doFilter(req, resp); 
    } 

    @Override 
    public void destroy() {} 
} 
1

은 간단하다 :

3

. 그 가치는 변하지 않았습니다.

나는 OP가 시도한 것과 같은 방법으로 을 사용하려고했는데 같은 문제가 있다고 생각한다 : 쿠키에 설정된 경로는 /이없는 컨텍스트 경로 였으므로 여전히 지워지지 않았다. (존재하지 않는 쿠키를 삭제하라는 명령을 내리고있었습니다).

내가 쿠키에 대한 컨텍스트 경로를 설정하는 라인을 제외하고 CookieClearLogoutHandler에 같은 글의 내 자신의 ProperCookieClearLogoutHandler, 쓰기, 결국 :

package com.testdomain.testpackage; 

import java.util.Arrays; 
import java.util.List; 

import javax.servlet.http.Cookie; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

import org.springframework.security.core.Authentication; 
import org.springframework.security.web.authentication.logout.LogoutHandler; 
import org.springframework.util.Assert; 
import org.springframework.util.StringUtils; 

public final class ProperCookieClearingLogoutHandler implements LogoutHandler { 
    private final List<String> cookiesToClear; 

    public ProperCookieClearingLogoutHandler(String... cookiesToClear) { 
     Assert.notNull(cookiesToClear, "List of cookies cannot be null"); 
     this.cookiesToClear = Arrays.asList(cookiesToClear); 
    } 

    public void logout(HttpServletRequest request, HttpServletResponse response, 
      Authentication authentication) { 
     for (String cookieName : cookiesToClear) { 
      Cookie cookie = new Cookie(cookieName, null); 
      String cookiePath = request.getContextPath() + "/"; 
      if (!StringUtils.hasLength(cookiePath)) { 
       cookiePath = "/"; 
      } 
      cookie.setPath(cookiePath); 
      cookie.setMaxAge(0); 
      response.addCookie(cookie); 
     } 
    } 
} 
다음

내가 spring-security.xml이 방법에 LogoutFilter에 대한 설정을 설정;

<bean id="logoutFilter" 
     class="org.springframework.security.web.authentication.logout.LogoutFilter"> 
     <constructor-arg name="logoutSuccessUrl" value="/views/login/login.xhtml?logout" /> 
     <constructor-arg> 
      <list> 
       <bean id="properCookieClearingLogoutHandler" 
        class="com.imatia.arpad.gplenos.authorization.ProperCookieClearingLogoutHandler"> 
        <constructor-arg name="cookiesToClear"> 
         <list> 
          <value>JSESSIONID</value> 
         </list> 
        </constructor-arg> 
       </bean> 
       <bean id="securityContextLogoutHandler" 
        class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"> 
       </bean> 
      </list> 
     </constructor-arg> 
     <property name="filterProcessesUrl" value="/logout" /> 
    </bean> 
0

스프링에서 제공하는 기본 CookieClearingLogoutHandler 수 인해 쿠키 경로의 차이에 명확하지 JSESSIONID.

쿠키 경로를 변경하면 안됩니다. 이렇게하면 쿠키 ID가 변경됩니다. 쿠키가/foo와 같은 경로로 설정되고이를 /로 변경하면 클라이언트는 변경된 쿠키를 원래 쿠키와 더 이상 연관시키지 않습니다. 쿠키는 이름과 경로로 식별됩니다.

위의 솔루션 ie (ProperCookieClearingLogoutHandler.class)와 같이 사용자 정의 CookieClearingLogoutHandler를 구현하고 아래 코드와 같이 스프링 보안으로 설정해야합니다. 대신 .deleteCookies ("JSESSIONID", "USER")를 사용하십시오. 기본적으로 CookieClearingLogoutHandler를 추가합니다.

봄 보안 자바 설정 :

@Configuration 
@EnableWebSecurity 
@ComponentScan(basePackages = "com.dentist.webapp") 
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { 

    @Autowired 
    private SessionRegistry sessionRegistry; 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http.authorizeRequests().antMatchers("/resources/**", "/signup/*", "/about", "/login/*").permitAll().anyRequest() 
       .authenticated() 
       .and().formLogin() 
           .loginPage("/login/form") 
           .permitAll() 
       .and().logout() 
           .invalidateHttpSession(true) 
           .clearAuthentication(true) 
          // .deleteCookies("JSESSIONID","USER") 
           .addLogoutHandler(new ProperCookieClearingLogoutHandler("JSESSIONID","USER")) 
           .permitAll() 
       .and().sessionManagement() 
           .maximumSessions(1) 
           .maxSessionsPreventsLogin(true) 
           .expiredUrl("/accessDenied") 
           .sessionRegistry(sessionRegistry); 

     } 

    } 
관련 문제