2013-04-11 15 views
5

Muszę usunąć plik cookie JSESSIONID, gdy użytkownik się wylogowuje. Aby to zrobić Dodałem następującej konfiguracji do mojego config Bezpieczeństwo:SpringSecurity: nie można usunąć 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> 

ale zamiast być usunięte, plik cookie jest po prostu stał duplikowane:

Old cookie

New cookie

więc nadal przekierowuje przeglądarkę do adresu URL "/ timeout".

Starałem się śledzić, co dzieje się za pomocą Narzędzia dla programistów w przeglądarce Chrome, a okazało się, że plik ten ustawia się z tego nagłówka odpowiedzi:

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

i usuwa z tego nagłówka odpowiedzi:

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

Nie jestem pewien, ale wygląda na to, że powodem jest pole "Ścieżka" tych nagłówków: w pierwszym wskazuje na "/ witryna /", aw drugim wskazuje na " /stronie internetowej".

Czy to jest przyczyna opisanych problemów? Jeśli to nie jest powód (lub nie jedyny powód), jaki jest inny powód (przyczyny)? Jak mam naprawić ten problem?

+0

Zobacz http://static.springsource.org/spring-security/site/docs/3.2.x/reference/springsecurity-single.html#ns-session- mgmt (sekcja 3.3.3) ... Niestety nie można zagwarantować, że będzie działać z każdym kontenerem serwletu, więc będziesz musiał przetestować go w swoim środowisku. Zobacz także powiązany przypis. – Ritesh

Odpowiedz

6

Nie trzeba jawnie usuwać ciasteczka JSESSIONID w ten sposób. Nie jest zarządzany przez Spring Security jako taki, ale przez twój kontener serwletów. Spring Security domyślnie unieważni sesję http po wylogowaniu, co z kolei spowoduje, że twój kontener serwletu usunie plik cookie JSESSIONID.

+2

http://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#ns-session-mgmt pokazuje, że jeśli używasz tagów zarządzania sesjami, być może będziesz musiał jawnie usuń plik cookie. – Richie

2

To jak ja unieważnić sesje:

<security:logout invalidate-session="true" logout-success-url="/myapp/auth/login" logout-url="/myapp/auth/logout" /> 
1

Jak usunąć na wylogowania jest prosta: wdrożyć wylogowanie i umieścić ten kod w metodzie:

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

sesji unieważnione spowoduje unieważnienie pliku cookie.

Ale próbowałem i okazało się, że po zamknięciu przeglądarki bez wylogowania, plik cookie JSESSIONID przetrwa i użytkownik może wejść do systemu po otwarciu przeglądarki.

Aby to wyeliminować, utworzyłem filtr, który unieważnia sesję przy logowaniu, tworząc nową sesję, w której logowanie będzie wykonywane od początku.

@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() {} 
} 
3

W moim przypadku z jakiegoś powodu mimo SecurityContextLogoutHandler rozmowy session.invalidate()JSESSIONID nie zostanie wyczyszczone. Jego wartość pozostała taka sama.

Próbowałem użyć delete-cookies="JSESSIONID" w taki sam sposób, jak próbował OP, i uważam, że miałem ten sam problem: Ścieżka ustawiona dla ciasteczka była ścieżką kontekstu bez końcówki /, więc nadal nie zostałaby wyczyszczona (Otrzymał polecenie usunięcia pliku cookie, który nie istnieje).

skończyło się pisać własne ProperCookieClearLogoutHandler, który jest identyczny do CookieClearLogoutHandler wyjątkiem linii, który wyznacza ścieżkę kontekstowe cookie:

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

Potem ustawić config dla LogoutFilter na spring-security.xml ten sposób;

<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

Domyślna CookieClearingLogoutHandler dostarczone przez sprężynę nie mógł jasno JSESSIONID powodu różnicy w ścieżce cookie.

Nie należy zmieniać ścieżki pliku cookie. To zmieniłoby tożsamość pliku cookie. Jeśli plik cookie został ustawiony dla ścieżki takiej jak/foo i zmienisz to na /, to klient nie będzie już kojarzył zmienionego pliku cookie z oryginalnym plikiem cookie. Plik cookie jest identyfikowany przez nazwę i ścieżkę.

Dlatego trzeba zaimplementować niestandardową CookieClearingLogoutHandler jak pokazano w powyższym roztworze tj (ProperCookieClearingLogoutHandler.class) i ustawić go do wiosny bezpieczeństwo jak pokazano poniżej kodu .Instead korzystania .deleteCookies („JSESSIONID”, „User”) który domyślnie dodaje CookieClearingLogoutHandler.

Wiosna zabezpieczeń Java config:

@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); 

     } 

    } 
Powiązane problemy