我正在使用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>
这是粗略的,我的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令牌?
好吧,经过几个小时的斗争,并试图解密在subject上播放频繁缺乏上下文的文档,我已经明白了。
所以,从他们的文档:
为了对非浏览器请求提供简单保护,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>
这将在交付给客户时呈现:
<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>
好的,几乎就在那里,现在我们必须创建我们的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._
....
<button id="deleteBookBtn" class="btn btn-danger"
data-csrf-name="@helper.CSRF.getToken.name"
data-csrf-value="@helper.CSRF.getToken.value"
data-delete-url="@routes.BooksController.destroy(book.id)"
data-redirect-url="@routes.HomeController.index()">Delete</button>
我无法在onclick()
事件中添加在线js,因为CSP也设置在2.6。
拒绝执行内联事件处理程序,因为它违反了以下内容安全策略指令:“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
<form method="post" id="myForm" action="someURL">
<input name="csrfToken" value="5965f0d244b7d32b334eff840...etc" type="hidden">
</form>
这是挣扎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配置中禁用csrf安全性,并且这也不会在控制台上提供405(Method Not Allowed)错误。
希望这会帮助人们.. !!
您可以使用Csrf-Token
选项添加headers
标头。
$.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 Documentation中所述,您可以使用Play生成的令牌设置'Csrf-Token
'标头:
如果您使用AJAX发出请求,可以将CSRF令牌放在HTML页面中,然后使用
Csrf-Token
标头将其添加到请求中。
在Scala-Template中,您可以使用@helper.CSRF.getToken.value
获取令牌值
在jQuerys Documentation之后,您可以通过使用ajaxSetup配置jQuery来为所有Ajax请求设置一次
$.ajaxSetup({
beforeSend: function(xhr) {
xhr.setRequestHeader('Csrf-Token', '@helper.CSRF.getToken.value');
}
});
或者通过配置headers
对象在每个请求上设置Header,如下所示:
$.ajax({
url: route.url,
...
headers: {
'Csrf-Token': '@helper.CSRF.getToken.value'
}
});