Поместите CSRF в заголовки в Spring 4.0.3 + Spring Безопасность 3.2.3 + Thymeleaf 2.1.2

У меня есть следующий код.

<!DOCTYPE html>

<html xmlns:th="http://www.thymeleaf.org">

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

<title>Fileupload Test</title>
</head>
<body>

 <p th:text="${msg}"></p>



<form action="#" th:action="@{/fileUpload}" method="post" enctype="multipart/form-data">
       <input type="file" name="myFile" />
       <input type="submit" />     
    </form>

</body>
</html>

Я получаю сообщение об ошибке HTTP 403: Недопустимый токен CSRF "null" был найден в параметре запроса "_csrf" или в заголовке "X-CSRF-TOKEN".

CSRF работает, если я использую эту строку вместо:

<form action="#" th:action="@{/fileUpload} + '?' + ${_csrf.parameterName} + '=' + ${_csrf.token}" method="post" enctype="multipart/form-data">

Но как я могу достичь рабочего CSRF, если я использую заголовки?

Ответ 1

После долгой борьбы с этой проблемой я, наконец, понял, почему код в официальной официальной документации Spring не работает... Обратите внимание на следующее:

<meta name="_csrf" content="${_csrf.token}" />
<meta name="_csrf_header" content="${_csrf.headerName}" />

Это документация с JSP! Поскольку мы используем Thymeleaf, вам нужно использовать th:content вместо content:

<meta name="_csrf" th:content="${_csrf.token}"/>
<meta name="_csrf_header" th:content="${_csrf.headerName}"/>

Теперь он работает!

Ответ 2

<!DOCTYPE html><html xmlns:th="http://www.thymeleaf.org"><head>
<meta name="_csrf" th:content="${_csrf.token}"/>
<!-- default header name is X-CSRF-TOKEN -->
<meta name="_csrf_header" th:content="${_csrf.headerName}"/>

и

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

$.ajax({
url: url,
method: 'DELETE',
success: function(result) {
    $('#table').bootstrapTable('remove', {
        field: 'id',
        values: [row.id]
    });
},
    error:function(result) {
    console.log(result);
}

});

Решена проблема с jquery ajax request delete. Я использую Spring Boot, Security и bootstrap -table.

Ответ 3

Лично используя ту же конфигурацию, что и вы (Thymleaf, Spring MVC, Spring Sec), я смог использовать meta csrf при загрузке через ajax и прямые вставки в URL-адрес действия при отправке стандартным образом. Поэтому используются различные типы форм:

например.

<form action="#" th:action="@{/fileUpload} + '?' + ${_csrf.parameterName} + '=' + ${_csrf.token}" method="post" enctype="multipart/form-data">

для стандартного представления

<form action="#" th:action="@{/fileUpload}" method="post" enctype="multipart/form-data">

со следующим javascript:

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

для отправки через Ajax/jQuery.

Основываясь на моих недавних исследованиях, похоже, нет чистой интеграции между ними и требуется небольшая модификация для работы кода.