user2000811
user2000811

Reputation: 271

Put CSRF into Headers in Spring 4.0.3 + Spring Security 3.2.3 + Thymeleaf 2.1.2

I have the following code:

<!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>

I get the error HTTP 403:

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

CSRF is working if I use this line instead:

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

But how can I achieve working CSRF if I use headers?

Upvotes: 19

Views: 12006

Answers (3)

goncalotomas
goncalotomas

Reputation: 1000

After fighting with this issue for some time, I finally figured out why the code in the official Spring documentation doesn't work... Notice the following:

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

This is documentation with JSP in mind! Since we are using Thymeleaf, what you need to do is to use th:content instead of content:

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

Now it works!

Upvotes: 26

Adriano Faria Alves
Adriano Faria Alves

Reputation: 177

<!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}"/>

and

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

});

Solved a problem with jquery ajax request delete .I use Spring Boot , Security and bootstrap -table .

Upvotes: 8

Aeseir
Aeseir

Reputation: 8434

Personally using same configuration as you (Thymleaf, Spring MVC, Spring Sec) i only was able to utilise meta csrf when uploading via ajax and direct inserts into action URL if submitting in standard fashion. So different types of forms used:

e.g.

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

for Standard submition

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

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

to submit via Ajax/jQuery.

Based on my recent research there doesn't seem to be a clean integration between the two and requires slight modifications to make code work.

Upvotes: 3

Related Questions