6

Tôi đang sử dụng Spring MVC/Security 3.X. Vấn đề là tôi nhận được 403 tại trang đăng nhập bất cứ khi nào các phiên timeout, nơi bên dưới "InvalidCsrfTokenException" đã được ném bởi spring framework:Cách tốt nhất để xử lý mã thông báo CSRF không hợp lệ được tìm thấy trong yêu cầu khi phiên làm việc nào trong bảo mật mùa xuân

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) 

Như Nó đề cập trong tài liệu lò xo các CSRF timeout là một vấn đề cần được xử lý một cách để xử lý tình huống này là phải có. tùy chỉnh AccessDeniedHandler nơi chúng tôi có ngoại lệ CSRF chặn. Một số thông tin như:

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

    } 
} 

Câu hỏi: Cách tốt nhất để xử lý tình huống này mà không phải làm mới trang (trải nghiệm người dùng xấu) hoặc có phiên không giới hạn là gì? Cảm ơn vì sự giúp đỡ của bạn trước đó.

+0

Bạn đang thực hiện cuộc gọi AJAX? – giubueno

+0

Tôi khuyên bạn nên gửi tiêu đề phản hồi Làm mới http sẽ làm mới trang ngay sau khi phiên hết hạn, tải lại hiệu quả và bắt đầu một phiên mới. Bạn cũng có thể chạy một số javascript trên các trang của bạn để cảnh báo người dùng khi phiên của họ sắp hết hạn –

+0

Có Tôi đang sử dụng cuộc gọi AJAX. Như tôi đã đề cập ở trên, tôi muốn tránh phiên tái tạo là vô tận. Vì vậy, có đầu làm mới không đáp ứng yêu cầu của tôi. Có JS để cảnh báo người dùng rằng phiên sắp hết hạn là một ý tưởng hay nhưng đối với trang đăng nhập. –

Trả lời

4

Cách đơn giản nhất tôi tìm thấy xử lý vô hiệu CSRF thẻ khi phiên lần ra tại trang đăng nhập là một trong các nội dung sau:

  1. Chuyển yêu cầu một lần nữa để lại trang đăng nhập 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. Quảng cáo d tiêu đề refresh như Neil McGuigan gợi ý:

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

  1. Hơn nữa bạn phải tạo một bean cho CustomAccessDeniedHandler mới và đăng ký nó. Ví dụ sau đây cho thấy điều này cho cấu hình Java.

Trong bất kỳ lớp cấu hình:

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

Trong cấu hình bảo mật của bạn thay đổi phương pháp cấu hình như sau:

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

Xem thêm here.

một giải pháp tối ưu hơn sẽ dành cho bảo mật mùa xuân để xử lý tình huống này trong khuôn khổ của họ.

-1

Khi sử dụng Xuân An, bạn phải gửi '_csrf', có các cách sau:

Trong Mẫu:

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

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

Nguồn: http://docs.spring.io/autorepo/docs/spring-security/3.2.0.CI-SNAPSHOT/reference/html/csrf.html

+0

Tôi đã làm điều đó. Vấn đề mà tôi gặp phải là mã thông báo CSRF không hợp lệ bất cứ khi nào phiên hết hạn, dẫn đến hành vi khó chịu trong trang LOGIN. –

Các vấn đề liên quan