Đã tìm thấy Mã thông báo CSRF không hợp lệ 'null' trên tham số yêu cầu '_csrf' hoặc tiêu đề 'X-CSRF-TOKEN'


90

Sau khi cấu hình Spring Security 3.2, _csrf.tokenkhông bị ràng buộc với một yêu cầu hoặc một đối tượng phiên.

Đây là cấu hình bảo mật mùa xuân:

<http pattern="/login.jsp" security="none"/>

<http>
    <intercept-url pattern="/**" access="ROLE_USER"/>
    <form-login login-page="/login.jsp"
                authentication-failure-url="/login.jsp?error=1"
                default-target-url="/index.jsp"/>
    <logout/>
    <csrf />
</http>

<authentication-manager>
    <authentication-provider>
        <user-service>
            <user name="test" password="test" authorities="ROLE_USER/>
        </user-service>
    </authentication-provider>
</authentication-manager>

Tệp login.jsp

<form name="f" action="${contextPath}/j_spring_security_check" method="post" >
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
    <button id="ingresarButton"
            name="submit"
            type="submit"
            class="right"
            style="margin-right: 10px;">Ingresar</button>
    <span>
        <label for="usuario">Usuario :</label>
        <input type="text" name="j_username" id="u" class="" value=''/>
    </span>
    <span>
        <label for="clave">Contrase&ntilde;a :</label>

        <input type="password"
               name="j_password"
               id="p"
               class=""
               onfocus="vc_psfocus = 1;"
               value="">
    </span>
</form>

Và nó hiển thị html tiếp theo:

<input type="hidden" name="" value="" />

Kết quả là trạng thái HTTP 403:

Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.

CẬP NHẬT Sau một số lần gỡ lỗi, đối tượng yêu cầu thoát ra khỏi biểu mẫu đẹp DelegateFilterProxy, nhưng trong dòng 469 của CoyoteAdapter, nó thực thi request.recycle (); sẽ xóa tất cả các thuộc tính ...

Tôi kiểm tra trong Tomcat 6.0.36, 7.0.50 với JDK 1.7.

Tôi không hiểu hành vi này, đúng hơn là có thể xảy ra nếu ai đó chỉ tôi theo hướng của một số cuộc chiến mẫu ứng dụng với Spring Security 3.2 hoạt động với CSRF.


1
Bạn sử dụng phiên bản Spring nào? Điều này tương tự hoạt động đối với tôi (tuy nhiên, có sự khác biệt trong spring-security.xml) với Spring 4.0.0 RELEASE (GA), Spring Security 3.2.0 RELEASE (GA) (mặc dù nó được tích hợp với Struts 2.3.16. Tôi không cung cấp cho nó một thử với Spring MVC thôi). Tuy nhiên, nó không thành công, khi yêu cầu nhiều phần để tải lên các tệp có trạng thái 403. Tôi đang đấu tranh để tìm giải pháp cho nó.
Tiny

Spring 3.2.6, Spring Security 3.2.0, CSRF, mã thông báo đã được thêm vào đối tượng http-request, đối tượng phiên giống nhau cùng với chuỗi yêu cầu, nhưng khi ra ngoài cho đến khi nó hiển thị jsp, loại bỏ tất cả các thuộc tính và chỉ để lại thuộc tính ... filter_applied
Hugo Robayo

@Tiny: Bạn đã bao giờ tìm ra lời giải cho bài toán nhiều phần chưa? Tôi đang gặp sự chính xác cùng một vấn đề.
Rob Johansen

1
@AlienBishop: Có, vui lòng kiểm tra câu trả lời này (nó sử dụng kết hợp Spring và Struts). Nếu bạn chỉ có Spring MVC thì hãy xem câu trả lời này . Cần lưu ý rằng thứ tự của các bộ lọc web.xmllà rất quan trọng. MultipartFilterphải được khai báo trước springSecurityFilterChain. Hy vọng rằng sẽ giúp. Cảm ơn.
Tiny

Câu trả lời:


110

Có vẻ như bảo vệ CSRF (Cross Site Request Forgery) trong ứng dụng Spring của bạn đã được bật. Trên thực tế, nó được bật theo mặc định.

Theo spring.io :

Khi nào bạn nên sử dụng bảo vệ CSRF? Khuyến nghị của chúng tôi là sử dụng bảo vệ CSRF cho bất kỳ yêu cầu nào có thể được xử lý bởi trình duyệt bởi người dùng bình thường. Nếu bạn chỉ đang tạo một dịch vụ được sử dụng bởi các máy khách không sử dụng trình duyệt, bạn có thể sẽ muốn tắt tính năng bảo vệ CSRF.

Vì vậy, để vô hiệu hóa nó:

@Configuration
public class RestSecurityConfig extends WebSecurityConfigurerAdapter {
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable();
  }
}

Nếu bạn muốn duy trì tính năng bảo vệ CSRF được bật thì bạn phải đưa vào biểu mẫu của mình csrftoken. Bạn có thể làm như thế này:

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

Bạn thậm chí có thể bao gồm mã thông báo CSRF trong hành động của biểu mẫu:

<form action="./upload?${_csrf.parameterName}=${_csrf.token}" method="post" enctype="multipart/form-data">

2
Đây nên được chấp nhận là câu trả lời vì nó không chỉ giải thích những gì cần làm mà còn những gì bạn nên cân nhắc trước khi làm điều gì đó để ngăn chặn những lỗi này.
Thomas Carlisle

1
Bạn cũng có thể làm.csrf().ignoringAntMatchers("/h2-console/**")
INSAN-e

Trong câu trả lời trên, tránh đi qua kiểu tham số truy vấn. Nếu bạn làm điều này, bạn đang để lộ token trước công chúng.
Pramod S. Nikam

31

Bạn không nên thêm vào biểu mẫu đăng nhập ?;

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

Như đã nêu ở đây trong tài liệu bảo mật mùa xuân


12

Nếu bạn sẽ đăng ký security="none"thì sẽ không có mã thông báo csrf nào được tạo. Trang sẽ không vượt qua bộ lọc bảo mật. Sử dụng vai trò BẤT CỨ.

Tôi đã không đi vào chi tiết, nhưng nó đang làm việc cho tôi.

 <http auto-config="true" use-expressions="true">
   <intercept-url pattern="/login.jsp" access="hasRole('ANONYMOUS')" />
   <!-- you configuration -->
   </http>

Tôi đang sử dụng security = none và việc chuyển đến câu trả lời của bạn đã giải quyết được vấn đề này. thật tuyệt vời khi thymeleaf tự động thêm mã thông báo csrf. Cảm ơn !
rxx

7

Hãy thử thay đổi này: <csrf /> như thế này: <csrf disabled="true"/>. Nó sẽ vô hiệu hóa csfr.


7

Với thymeleaf, bạn có thể thêm:

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


4

Tôi đã từng có cùng một vấn đề.

Cấu hình của bạn sử dụng security = "none" nên không thể tạo _csrf:

<http pattern="/login.jsp" security="none"/>

bạn có thể đặt access = "IS_AUTHENTICATED_ANONYMOUSLY" cho trang /login.jsp thay thế cấu hình trên :

<http>
    <intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
    <intercept-url pattern="/**" access="ROLE_USER"/>
    <form-login login-page="/login.jsp"
            authentication-failure-url="/login.jsp?error=1"
            default-target-url="/index.jsp"/>
    <logout/>
    <csrf />
</http>


1

Vui lòng xem ứng dụng mẫu làm việc của tôi trên Github và so sánh với thiết lập của bạn.


Tôi sẽ hạ cấp xuống mùa xuân 3.2.6, tôi hy vọng nó hoạt động mà không cần mvc mùa xuân.
Hugo Robayo

Có, nó sẽ hoạt động mà không có vấn đề gì vì tôi đã tạo ứng dụng mẫu từ ứng dụng hiện có của mình trên Spring 3.1.4.
manish

ha ha ha ha ha, tuyệt vời, để làm cho nó hoạt động chỉ là hạ cấp không phải là giải pháp bhaiya ji @manish
Kuldeep Singh

1

Cả hai giải pháp đều không hiệu quả với tôi. Cái duy nhất phù hợp với tôi ở dạng Spring là:

action = "./ upload? $ {_ csrf.parameterName} = $ {_ csrf.token}"

THAY THẾ BẰNG:

action = "./ upload? _csrf = $ {_ csrf.token}"

(Mùa xuân 5 với csrf được bật trong cấu hình java)


0

Trong bộ điều khiển của bạn, hãy thêm những thứ sau:

@RequestParam(value = "_csrf", required = false) String csrf

Và trên trang jsp thêm

<form:form modelAttribute="someName" action="someURI?${_csrf.parameterName}=${_csrf.token}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.