如何在表单的AJAX post请求中传递CSRF令牌?

Nat*_*H06 12 ajax jquery scala csrf playframework

我正在使用Scala Play!2.6框架,但这可能不是问题.我正在使用他们的Javascript路由 - 它似乎工作正常,但它有问题.我有一个表单,在渲染时产生这个,带有CSRF令牌:

<form method="post" id="myForm" action="someURL">

<input name="csrfToken" value="5965f0d244b7d32b334eff840...etc" type="hidden">
  <input type="text" id="sometext">
  <button type="submit"> Submit! </button>

</form>
Run Code Online (Sandbox Code Playgroud)

这是粗略的,我的AJAX:

$(document).on('submit', '#myForm', function (event) {

 event.preventDefault();
   var data = {
    textvalue: $('#sometext').val()
   }
 var route = jsRoutes.controllers.DashboardController.postNewProject()
 $.ajax({
    url: route.url,
    type: route.type,
    data : JSON.stringify(data),
    contentType : 'application/json',
    success: function (data) { ...      },
    error: function (data) { ...  }
        })

});
Run Code Online (Sandbox Code Playgroud)

但是当我发布这个时,我从我的服务器获得了一个UNAUTHORIZED响应,我在IntelliJ中的控制台告诉我CSRF检查失败了.我如何在请求中传递CSRF令牌?

Nat*_*H06 21

好吧,经过几个小时的斗争,并尝试解密Play的频繁缺乏上下文 - 关于这个主题的文档,我已经得到了它.

所以,从他们的文档:

为了对非浏览器请求提供简单保护,Play仅在标头中检查带有cookie的请求.如果您使用AJAX发出请求,可以将CSRF令牌放在HTML页面中,然后使用Csrf-Token标头将其添加到请求中.

然后没有代码或示例.谢谢玩.非常具有描述性.无论如何,这是如何:

view.html.formTemplate你可以在IntelliJ中写一下:

@()
<form method="post" id="myForm" action="someURL">

@helper.CSRF.formField  <!-- This auto-generates a token for you -->
  <input type="text" id="sometext">
  <button type="submit"> Submit! </button>

</form>
Run Code Online (Sandbox Code Playgroud)

这将在交付给客户时呈现:

<form method="post" id="myForm" action="someURL">

<input name="csrfToken" value="5965f0d244b7d32b334eff840...etc" type="hidden">
  <input type="text" id="sometext">
  <button type="submit"> Submit! </button>

</form>
Run Code Online (Sandbox Code Playgroud)

好的,几乎就在那里,现在我们必须创建我们的AJAX调用.我将我的所有内容都放在一个单独的main.js文件中,但view.html.formTemplate如果你愿意,你也可以将它放在你的文件中.

$(document).on('submit', '#myForm', function (event) {

 event.preventDefault();
   var data = {
    myTextToPass: $('#sometext').val()
   }
 // LOOK AT ME! BETWEEN HERE AND
 var token =  $('input[name="csrfToken"]').attr('value')
    $.ajaxSetup({
        beforeSend: function(xhr) {
            xhr.setRequestHeader('Csrf-Token', token);
        }
    });
// HERE
 var route = jsRoutes.controllers.DashboardController.postNewProject()
 $.ajax({
    url: route.url,
    type: route.type,
    data : JSON.stringify(data),
    contentType : 'application/json',
    success: function (data) { ...      },
    error: function (data) { ...  }
        })

});
Run Code Online (Sandbox Code Playgroud)

使用此行: var token = $('input[name="csrfToken"]').attr('value') 您正在选择在表单字段中自动生成的CSRF令牌,并在var中获取其值以在Javascript中使用.

来自AJAX的另一个重要组块是:

$.ajaxSetup({
            beforeSend: function(xhr) {
                xhr.setRequestHeader('Csrf-Token', token);
            }
        });
Run Code Online (Sandbox Code Playgroud)

使用$.ajaxSetup,您可以设置标题中的内容.这是你必须从他们的文档推断:

使用Csrf-Token标头将其添加到请求中.

祝好运!如果这一点很清楚,请告诉我.


注意:使用lusca时,请使用X-CSRF-Token而不是Csrf-Token.


MOn*_*key 6

从 JSP

<form method="post" id="myForm" action="someURL">
    <input name="csrfToken" value="5965f0d244b7d32b334eff840...etc" type="hidden">    
</form>
Run Code Online (Sandbox Code Playgroud)

这是在挣扎了 3 小时后对我有用的最简单的方法,只需像这样从输入隐藏字段中获取令牌,并且在执行 AJAX 请求时只需要在标头中传递此令牌,如下所示:-

来自 JQuery

var token =  $('input[name="csrfToken"]').attr('value'); 
Run Code Online (Sandbox Code Playgroud)

来自普通的 Javascript

var token = document.getElementsByName("csrfToken").value;
Run Code Online (Sandbox Code Playgroud)

最终的 AJAX 请求

$.ajax({
          url: route.url,
          data : JSON.stringify(data),
          method : 'POST',
          headers: {
                        'X-CSRFToken': token 
                   },
          success: function (data) { ...      },
          error: function (data) { ...  }
});
Run Code Online (Sandbox Code Playgroud)

现在你不需要在 web 配置中禁用 crsf 安全性,而且这不会在控制台上给你 405(Method Not Allowed) 错误。

希望这会帮助人们.. !!