6

Używam Spring MVC/Security 3.X. Problem polega na tym, że za każdym razem uzyskuję 403 na stronie logowania timeout sesja, gdzie pod „InvalidCsrfTokenException” jest wyrzucane przez Spring Framework:Jaki jest najlepszy sposób obsługi Nieważny token CSRF znaleziony w żądaniu, gdy przekroczono limit czasu sesji w Spring Security

threw exception [org.springframework.security.web.csrf.InvalidCsrfTokenException: Invalid CSRF Token '7b4aefe9-6685-4c70-adf1-0d633680523a' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.] with root cause 
org.springframework.security.web.csrf.InvalidCsrfTokenException: Invalid CSRF Token '7b4aefe9-6685-4c70-adf1-0d633680523a' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'. 
    at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:100) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192) 
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) 
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343) 
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) 
    at org.springframework.web.multipart.support.MultipartFilter.doFilterInternal(MultipartFilter.java:119) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) 
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) 
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) 
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070) 
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611) 
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:314) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 
    at java.lang.Thread.run(Thread.java:745) 

jak to wspomniano w dokumentacji wiosennej CSRF timeout jest problem, który należy obchodzić Jednym ze sposobów, aby obsługiwać ten scenariusz jest mieć. niestandardowy obiekt AccessDeniedHandler, w którym przechwytywany jest wyjątek CSRF. Coś takiego:

static class CustomAccessDeniedHandler extends AccessDeniedHandlerImpl{ 

    @Override 
    public void handle(HttpServletRequest request, 
      HttpServletResponse response, 
      AccessDeniedException accessDeniedException) 
      throws IOException, ServletException { 
     if (accessDeniedException instanceof MissingCsrfTokenException 
       || accessDeniedException instanceof InvalidCsrfTokenException) { 

      //What goes in here??? 

     } 

     super.handle(request, response, accessDeniedException); 

    } 
} 

Pytanie: Jaki jest najlepszy sposób na poradzenie sobie z tą sytuacją bez konieczności odświeżania strony (co jest niekorzystne dla użytkownika) lub niekończącej się sesji? Dzięki za pomoc z góry.

+0

Czy robisz połączenie AJAX? – giubueno

+0

Polecam wysłanie nagłówka Odśwież nagłówek http, który odświeży stronę zaraz po wygaśnięciu sesji, skutecznie ją wczytując i rozpoczynając nową sesję. Możesz również uruchomić javascript na swoich stronach, aby ostrzec użytkownika, gdy jego sesja wkrótce wygaśnie. –

+0

Tak Używam wywołania AJAX. Jak wspomniałem powyżej, chciałbym uniknąć niekończącej się sesji odnawialnej. A więc odświeżenie głowy nie spełnia moich wymagań. Posiadanie JS, aby ostrzec użytkownika, że ​​sesja wkrótce wygaśnie jest dobrym pomysłem, ale dla strony logowania. –

Odpowiedz

4

Najprostszym sposobem znalazłem się rączką invalidate CSRF tokena podczas czasu sesji na stronie logowania jest jednym z poniższych:

  1. Przekierowanie ponownie żądanie ponownie stronę logowania vi CustomAccessDeniedHandler:

    static class CustomAccessDeniedHandler extends AccessDeniedHandlerImpl{ 
    
    
    
    
        @Override 
        public void handle(HttpServletRequest request, 
          HttpServletResponse response, 
    
        AccessDeniedException accessDeniedException) 
        throws IOException, ServletException { 
    if (accessDeniedException instanceof MissingCsrfTokenException 
         || accessDeniedException instanceof InvalidCsrfTokenException) { 
    
        if(request.getRequestURI().contains("login")){ 
         response.sendRedirect(request.getContextPath()+"/login");           
        } 
    } 
    
    super.handle(request, response, accessDeniedException); 
    
    
    
    } 
    } 
    
  2. Reklama d nagłówek Refresh jak Neil McGuiganem zasugerował:

<meta http-equiv="refresh" content="${pageContext.session.maxInactiveInterval}">

  1. Ponadto należy utworzyć ziarna dla nowego CustomAccessDeniedHandler i zarejestrować go. Poniższy przykład pokazuje to dla konfiguracji Java.

W każdej klasie config:

@Bean 
public AccessDeniedHandler accessDeniedHandler() { 
    return new CustomAccessDeniedHandler(); 
} 

W swojej konfiguracji zabezpieczeń zmodyfikować metodę configure następująco:

@Override 
protected void configure(final HttpSecurity http) throws Exception { 
    http 
     // ... 
     .and() 
     .exceptionHandling().accessDeniedHandler(accessDeniedHandler()); 
} 

zobaczyć również here.

więcej Optymalne rozwiązanie będzie dla Spring Security, aby poradzić sobie z tą sytuacją w ich ramach.

-1

Podczas korzystania Wiosna Security, należy wysłać '_csrf', istnieją następujące sposoby:

w formie:

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>

W Ajax:

<head> <meta name="_csrf" content="${_csrf.token}"/> <!-- default header name is X-CSRF-TOKEN --> <meta name="_csrf_header" content="${_csrf.headerName}"/> <!-- ... --> </head>

$(function() { 
    var token = $("meta[name='_csrf']").attr("content"); 
    var header = $("meta[name='_csrf_header']").attr("content"); 
    $(document).ajaxSend(function(e, xhr, options) { 
    xhr.setRequestHeader(header, token); 
    }); 
}); 

Źródło: http://docs.spring.io/autorepo/docs/spring-security/3.2.0.CI-SNAPSHOT/reference/html/csrf.html

+0

Już to robię. Problem, który mam, polega na tym, że token CSRF staje się niepoprawny za każdym razem, gdy skończy się sesja, co doprowadzić do nieprzyjemnego zachowania na stronie LOGIN. –

Powiązane problemy