【问题标题】:How to add csrf token to ajax request如何将 csrf 令牌添加到 ajax 请求
【发布时间】:2016-09-19 21:43:51
【问题描述】:

我在将 csrf 添加到 ajax 请求时遇到问题。我在客户端使用带有 spring-boot/spring 安全性的 thymeleaf。 Spring security 不允许该请求,因为缺少 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();

}

我们将不胜感激

【问题讨论】:

    标签: ajax spring spring-security thymeleaf


    【解决方案1】:

    我修改了@Prakash Hari Sharma 的解决方案,并获得了对我有用的以下代码。注意,th: 前缀如果使用 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();
    

    希望这对某人也有帮助。

    【讨论】:

      【解决方案2】:

      作为@EdwardoS 答案的补充,在将元标记添加到&lt;head&gt; 元素后:

      百里香:

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

      JSP:

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

      ...然后您可以执行Spring documentation 中的建议,并让您未来的所有 ajax 包含csrf

      $(function () {
          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);
          });
      });
      

      【讨论】:

        【解决方案3】:

        在spring文档中,出于安全考虑,也建议不要在GET请求中使用csrf token

        “确定接收令牌的请求范围的能力有助于保护 防止将 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);
                }
            });
        });
        

        &lt;head&gt; 元素中的元标记与之前的答案相同:

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

        【讨论】:

          【解决方案4】:

          将 CSRF Token 存储在您的 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();
          

          【讨论】:

          • 我应用了上面的代码,但仍然出现禁止错误。然后我将上面代码中的所有变量行替换为: var token = $("meta[name='_csrf']").attr("content"); var header = $("meta[name='_csrf_header']").attr("content");并且问题解决了。感谢您的帮助!
          • 对于 Thymeleaf,只需在上面的元数据中将 th: 前缀为“名称”和“内容”。我正在使用 Thymleaf,这就是我所做的。
          【解决方案5】:

          你可以在下面找到我的代码来使用 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);
              });
          

          【讨论】:

            【解决方案6】:

            您可以将 Spring Security 的 CSRF Token 设置为名为 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。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2019-11-30
              • 2019-12-22
              • 2018-08-09
              • 2015-04-09
              • 1970-01-01
              • 2013-09-13
              • 2020-02-04
              • 2018-07-28
              相关资源
              最近更新 更多