2016-04-11 15 views
5

Wiem, że istnieje wiele artykułów na ten temat, ale mam problem i nie mogę znaleźć żadnego rozwiązania.Wylogowanie z usługi Spring Security nie działa - nie usuwa kontekstu zabezpieczeń, a uwierzytelniony użytkownik nadal istnieje.

mam klasyczną java bezpieczeństwo wiosna config:

@Configuration 
@EnableWebSecurity 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

@Autowired 
private AuctionAuthenticationProvider auctionAuthenticationProvider; 

@Autowired 
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { 
    auth.authenticationProvider(auctionAuthenticationProvider); 
} 

@Override 
protected void configure(HttpSecurity http) throws Exception { 
    http.httpBasic(); 

    ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry authorizeRequest = http.authorizeRequests(); 

    configureAdminPanelAccess(authorizeRequest); 
    configureFrontApplicationAccess(authorizeRequest); 
    configureCommonAccess(authorizeRequest); 

    http.csrf() 
     .csrfTokenRepository(csrfTokenRepository()).and() 
     .addFilterAfter(csrfHeaderFilter(), CsrfFilter.class); 

    http.logout() 
     .clearAuthentication(true) 
     .invalidateHttpSession(true); 
} 
... 
} 

Ponadto, mam dwie metody kontrolera, gdzie Logowanie/wylogowanie z mojej aplikacji internetowych AJAX.

Kiedy chcę się wylogować, najpierw nazywam tę metodę, która polega na usuwaniu sesji użytkownika i usuwaniu wszystkiego z kontekstu zabezpieczeń.

@Override 
@RequestMapping(value = "/logout", method = GET, produces = APPLICATION_JSON_UTF8_VALUE) 
public ResponseEntity<Boolean> logout(final HttpServletRequest request, final HttpServletResponse response) { 
    Authentication auth = SecurityContextHolder.getContext().getAuthentication(); 
    if (auth != null){ 
     new SecurityContextLogoutHandler().logout(request, response, auth); 
    } 

    return new ResponseEntity<>(Boolean.TRUE, HttpStatus.OK); 
} 

Po tym ja odświeżyć moją aplikację internetową klienta i za każdym razem, gdy jest załadowany, to sprawdzić, czy użytkownik jest uwierzytelniony przez wywołanie następującej metody kontrolera:

@Override 
@RequestMapping(value = "/user", method = GET, produces = APPLICATION_JSON_UTF8_VALUE) 
public ResponseEntity<UserDetails> user() { 
    Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 
    if (principal instanceof UserDetails) { 
     return new ResponseEntity<>((UserDetails) principal, HttpStatus.OK); 
    } 

    return null; 
} 

i tu wynos odbierać ostatni uwierzytelniony użytkownik. Wygląda na to, że w poprzedniej metodzie wylogowania Spring Logout nie działa.

Należy pamiętać, że starałem się wylogować z następującego kodu, bez powodzenia:

@Override 
    @RequestMapping(value = "/logout", method = GET, produces = APPLICATION_JSON_UTF8_VALUE) 
    public ResponseEntity<Boolean> logout(final HttpServletRequest request) { 
    try { 
     request.logout(); 

     return new ResponseEntity<>(Boolean.TRUE, HttpStatus.OK); 
    } catch (ServletException ex) { 
     if (LOG.isDebugEnabled()) { 
      LOG.debug("There is a problem with the logout of the user", ex); 
     } 
    } 

Czy masz jakiś pomysł, co mi brakuje w moim config i procesu wylogowania?

Odpowiedz

18

Z Twojego pytania wynika, że ​​próbujesz utworzyć własne wylogowanie, a także próbujesz użyć domyślnego wylogowania wiosennego. Zalecamy wybranie tylko jednej metody, która nie spowoduje ich wzajemnego wymieszania. Istnieją dwie możliwości: aby wylogować się z wiosną:

pierwsze: Domyślnie wylogowanie bezpieczeństwo wiosna

.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")) 
.logoutSuccessUrl("/logout.done").deleteCookies("JSESSIONID") 
.invalidateHttpSession(true) 

z przykładu powyżej, powinny trzeba tylko zadzwonić do /logout url kiedy chcesz, aby wylogować użytkownika. Nie trzeba tworzyć żadnego @Controller, aby obsłużyć to wylogowanie, a zamiast tego wiosna pomoże zalogować użytkownika. Możesz też dodać coś, co chcesz unieważnić tutaj.

drugie: Proggrammatically wylogować

@RequestMapping(value = {"/logout"}, method = RequestMethod.POST) 
public String logoutDo(HttpServletRequest request,HttpServletResponse response){ 
HttpSession session= request.getSession(false); 
    SecurityContextHolder.clearContext(); 
     session= request.getSession(false); 
     if(session != null) { 
      session.invalidate(); 
     } 
     for(Cookie cookie : request.getCookies()) { 
      cookie.setMaxAge(0); 
     } 

    return "logout"; 
} 

Jeśli używasz tego wylogowania, to nie musi obejmować pierwszą metodę w konfiguracji zabezpieczeń wiosny. Korzystając z tej metody, możesz dodać dodatkową akcję przed i po wylogowaniu. Później, aby użyć tego wylogowania, po prostu zadzwoń pod jeden adres URL, a użytkownik zostanie wylogowany ręcznie. Ta metoda spowoduje unieważnienie sesji, wyczyszczenie kontekstu zabezpieczeń sprężyny i plików cookie.

Dodatkowo dla drugiej metody, jeśli używasz RequestMethod.POST, musisz uwzględnić klucz csrf jako post. Alternatywnym sposobem jest utworzenie formularza z ukrytym wejściowym kluczem csrf. To niektóre z przykładów auto generowane linku wylogowania z jQuery:

$("#Logout").click(function(){ 
    $form=$("<form>").attr({"action":"${pageContext.request.contextPath}"+"/logout","method":"post"}) 
    .append($("<input>").attr({"type":"hidden","name":"${_csrf.parameterName}","value":"${_csrf.token}"})) 
    $("#Logout").append($form); 
    $form.submit(); 
}); 

Wystarczy utworzyć hiperłącze <a id="Logout">Logout</a> go używać.

Jeśli używasz RequestMethod.GET, tylko to klucz CSRF jako parametr w połączeniu tak:

<a href="${pageContext.request.contextPath}/logout?${_csrf.parameterName}=${_csrf.token}">Logout</a> 

to wszystko, mam nadzieję jej pomocy.

+1

Witam, Freezy. Właściwie miałeś rację - wymieszałem oba sposoby konfiguracji. To, co robię, to usunąć tylko kod z mojego SecurityConfig związanego z wylogowaniem i zachować bieżącą implementację kontrolera. Teraz działa poprawnie. Dzięki – Streetsouls

+0

próbowałem twojej pierwszej metody, ale to nie działa ... –

+0

To samo co Black Swan, pierwsza prośba o metodę z POST lub GET i z lub bez sprawdzenia CSRF, przekierowuje mnie, ale wciąż jestem zalogowany :(wszelkie pomysły na wierzchu swoich umysłów? – Alex

0

Pomoże to, myślę clearAuthentication (prawda), to wystarczy:

@Configuration 
@EnableWebSecurity 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

.... 

    @Override 
    protected void configure(HttpSecurity http) throws Exception 
    { 
     http 
     .httpBasic() 
     .and() 
     .logout().clearAuthentication(true) 
     .logoutSuccessUrl("/") 
     .deleteCookies("JSESSIONID") 
     .invalidateHttpSession(true) 
     .and() 
Powiązane problemy