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

我正在使用Scala Play! 2.6框架,但这可能不是问题。 我正在使用他们的Javascript路由 – 它似乎工作正常,但它有问题。 我有一个表单,当使用CSRF令牌进行渲染时会生成此表单:

这是粗略的,我的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) { ... } }) }); 

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

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

所以,从他们的文档:

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

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

在您的view.html.formTemplate您可以使用IntelliJ编写:

 @() 
@helper.CSRF.formField

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

 

好的,几乎就在那里,现在我们必须创建我们的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) { ... } }) }); 

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

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

 $.ajaxSetup({ beforeSend: function(xhr) { xhr.setRequestHeader('Csrf-Token', token); } }); 

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

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

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


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

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

感谢NateH06的标题名称! 我试图发送带有ajax函数调用的“删除”按钮的csrf令牌,我被困在以下内容:

 @import helper._ ....  

由于在游戏2.6上设置了CSP,我无法在onclick()事件中添加在线js。

拒绝执行内联事件处理程序,因为它违反了以下内容安全策略指令:“default-src’self’”。

在JS文件上:

 function sendDeleteRequest(event) { url = event.target.getAttribute("data-delete-url") redirect = event.target.getAttribute("data-redirect-url") csrfTokenName = event.target.getAttribute("data-csrf-name") csrfTokenValue = event.target.getAttribute("data-csrf-value") $.ajax({ url: url, method: "DELETE", beforeSend: function(request) { //'Csrf-Token' is the expected header name, not $csrfTokenName request.setRequestHeader(/*$csrfTokenName*/'Csrf-Token', csrfTokenValue); }, success: function() { window.location = redirect; }, error: function() { window.location.reload(); } }) } var deleteBookBtn = document.getElementById("deleteBookBtn"); if(deleteBookBtn) { deleteBookBtn.addEventListener("click", sendDeleteRequest); } 

将标题名称设置为'Csrf-Token' ,ajax调用完美无缺!

来自JSP

 

这是在努力工作3小时后对我有用的最简单的方法,只需从输入隐藏字段中获取令牌,同时执行AJAX请求,只需要在标头中传递此令牌,如下所示: –

来自JQuery

 var token = $('input[name="csrfToken"]').attr('value'); 

从简单的Javascript

 var token = document.getElementsByName("csrfToken").value; 

最终的AJAX请求

 $.ajax({ url: route.url, data : JSON.stringify(data), method : 'POST', headers: { 'X-CSRF-Token': token }, success: function (data) { ... }, error: function (data) { ... } 

});

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

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

您可以使用headers选项添加Csrf-Tokenheaders

 $.ajax({ url: '@routes.MyController.myPostAction()', method: 'post', headers: { 'Csrf-Token': '@play.filters.csrf.CSRF.getToken.map(_.value)' }, data: { name: '@name' }, success: function (data, textStatus, jqXHR) { location.reload(); }, error: function (jqXHR, textStatus, errorThrown) { debugger; } }); 

如Play Framework 2.6文档中所述 ,您可以使用Play生成的令牌设置“ Csrf-Token ”标头:

如果您使用AJAX发出请求,可以将CSRF令牌放在HTML页面中,然后使用Csrf-Token标头将其添加到请求中。

在Scala-Template中,您可以使用@helper.CSRF.getToken.value获取令牌值

在jQuerys文档之后,您可以通过使用ajaxSetup配置jQuery来为所有Ajax请求设置一次

 $.ajaxSetup({ beforeSend: function(xhr) { xhr.setRequestHeader('Csrf-Token', '@helper.CSRF.getToken.value'); } }); 

或者通过配置headers对象来设置每个请求上的headers如下所示:

 $.ajax({ url: route.url, ... headers: { 'Csrf-Token': '@helper.CSRF.getToken.value' } });