Поместите 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.
Основываясь на моих недавних исследованиях, похоже, нет чистой интеграции между ними и требуется небольшая модификация для работы кода.