如何将csrf标记添加到ajax请求

时间:2016-05-23 06:14:42

标签: ajax spring spring-security thymeleaf

我在向ajax请求添加csrf时遇到问题。我在客户端使用百日咳采用弹簧/弹簧安全装置。 Spring安全性不允许该请求,因为缺少csrf-token。这是我的ajax代码

function bits(){
    var xhttp = new XMLHttpRequest();
    var selected = document.getElementById("product").value;
    xhttp.onreadystatechange = function(){
      if(xhttp.readyState==4 && xhttp.status==200){
        var result= JSON.parse(xhttp.responseText)
        var length = result.length;
        for(i=0; i<length; i++){

           console.log(result[k].spid);
        }
    }

};

 xhttp.open("POST", "http://localhost:8080/bids?q="+selected,  true);
 xhttp.send();

}

帮助将不胜感激

6 个答案:

答案 0 :(得分:10)

我修改了@Prakash Hari Sharma的解决方案并使用了以下代码。注意,如果使用Thymeleaf,则为:前缀。

- 标题部分

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

Ajax脚本函数

...
...
var token = $("meta[name='_csrf']").attr("content"); 
var header = $("meta[name='_csrf_header']").attr("content");
...
...
xhttp.open("POST", "http://localhost:8080/bids?q="+selected,  true);
xhttp.setRequestHeader(header, token);
xhttp.send();

希望这也有助于某人。

答案 1 :(得分:4)

作为@EdwardoS答案的补充,将元标记添加到$scope.lists = { "count": 6, "brands": [{ "number": 9, "brand": "aaaaa" }, { "number": 3, "brand": "project management" }, { "number": 2, "brand": "adasdadasd" }, { "number": 2, "brand": "gsdfgrtwetwert" }, { "number": 2, "brand": "dfghgdfghdfgh" }, { "number": 2, "brand": "dfghdfghrtr" }] }; 元素后:

Thymeleaf:

<head>

JSP:

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

...然后,您可以执行Spring documentation中建议的操作,并将所有未来的ajax包含在<meta name="_csrf" content="${_csrf.token}"/> <meta name="_csrf_header" content="${_csrf.headerName}"/> 中:

csrf

答案 2 :(得分:3)

将CSRF令牌存储在您的jsp元标记中

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

并在ajax请求中添加csrf标记的值

var elementToken = document.querySelector('meta[property="_csrf"]');
var token = elementToken && elementToken.getAttribute("content");
var elementHeader = document.querySelector('meta[property="_csrf_header"]');
var header = elementHeader && elementHeader.getAttribute("content");
xhttp.open("POST", "http://localhost:8080/bids?q="+selected,  true);
xmlhttp.setRequestHeader(header, token);
xhttp.send();

答案 3 :(得分:3)

在spring文档中,还建议您出于安全原因不在GET请求中使用csrf令牌

  

“能够确定接收令牌的请求的范围有助于防范   反对将CSRF令牌泄露给第三方。“

因此,您可以通过以下方式过滤仅为POST请求传递令牌:

$(function() {
    var token = $("meta[name='_csrf']").attr("content");
    var header = $("meta[name='_csrf_header']").attr("content");
    $(document).ajaxSend(function(e, xhr, options) {
        if (options.type == "POST") {
            xhr.setRequestHeader(header, token);
        }
    });
});

<head>元素中的元标记与之前的答案相同:

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

答案 4 :(得分:2)

在下面你可以找到我的代码以使用ajax和csrf。我也使用Spring Security。

    // In your JSP meta tags
    <meta name="_csrf" content="${_csrf.token}"/>
    <!-- default header name is X-CSRF-TOKEN -->
    <meta name="_csrf_header" content="${_csrf.headerName}"/>

    // In your javascript
    // CSRF Variables
    var _tc = $("meta[name='_csrf']").attr("content");
    var _hc = $("meta[name='_csrf_header']").attr("content");


    // Header
    var headersStomp = {};
    headersStomp[_hc] = _tc;

    $(document).ajaxSend(function(e, xhr, options) {
        xhr.setRequestHeader(_hc, _tc);
    });

答案 5 :(得分:0)

您可以将Spring Security的CSRF令牌设置为名为MyApp.csrfToken的Javascript变量。

JSP 中,添加流动的脚本,在文档准备就绪后调用init函数:

<script type="text/javascript">
    document.onreadystatechange = function () {
       var state = document.readyState;
       if (state == 'complete') {
         fnInit("${_csrf.parameterName}", "${_csrf.token}"); 
       }
    }​;
</script>

JS 文件中,定义fnInit函数

var MyApp = MyApp || {};
function fnInit(csrfParam, csrfToken) {
  MyApp.csrfToken = {
      param : csrfParam,
      value : csrfToken
  }
}

现在,您可以在任何ajax调用中使用准备好使用

...
...
xhttp.open("POST", "http://localhost:8080/bids?q="+selected + "&"+ MyApp.csrfToken.param+"="+ MyApp.csrfToken.value,  true);
xhttp.send();

PS:对于jQuery不需要,它是纯JavaScript。