Как передать токен CSRF в запросе AJAX post для формы?
Я использую 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>
и вот, примерно, мой Аякс:
$(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) { ... }
})
});
но когда я публикую это, я получаю несанкционированный ответ с моего сервера, и моя консоль в IntelliJ говорит мне, что проверка CSRF не выполняется. Как бы я прошел по CSRF токен в запросе?
5 ответов
хорошо, после борьбы с этим в течение нескольких часов и попытки расшифровать часто отсутствующую контекстную документацию Play на теме, я понял.
Итак, из их документов:
чтобы обеспечить простую защиту для не запросов браузера, играть только проверки запросы с cookies в заголовке. Если вы делаете запросы с 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. У меня все свои в отдельной магистрали.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-токена заголовок.
удачи! Дай мне знать, если все ясно.
Примечание при использовании lusca используйте X-CSRF-Token
вместо Csrf-Token
.
добавьте его в запрос, используя
Csrf-Token
заголовок.
спасибо NateH06 название заголовка! Я пытался отправить токен csrf для кнопки "удалить" с вызовом функции ajax, и я застрял на следующем:
@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>
Я не смог добавить онлайн js в onclick()
событие из-за CSP, установленного на play 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>
Это самый простой способ, который работал для меня после борьбы за 3hrs, просто получите токен из скрытого поля ввода, как это, и при выполнении запроса 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) { ... }
});
теперь вам не нужно отключать безопасность crsf в web config, и также это не даст вам ошибку 405( метод не разрешен) на консоли.
надеюсь, это поможет людям..!!
вы можете добавить Csrf-Token
заголовок .
$.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 Документация, вы можете установить 'Csrf-Token
' заголовок с токеном, генерируемым Play:
если вы делаете запросы с AJAX, вы можете разместить токен CSRF на странице HTML, а затем добавить его в запрос с помощью
Csrf-Token
заголовок.
в шаблоне Scala вы можете получить значение токена, используя @helper.CSRF.getToken.value
после документация jQuerys вы можете либо установить его один раз для всех запросов Ajax, настроив jQuery с помощью метода ajaxsetup
$.ajaxSetup({
beforeSend: function(xhr) {
xhr.setRequestHeader('Csrf-Token', '@helper.CSRF.getToken.value');
}
});
или альтернативно установите заголовок для каждого запроса, настроив headers
объект вроде этого:
$.ajax({
url: route.url,
...
headers: {
'Csrf-Token': '@helper.CSRF.getToken.value'
}
});