AjaxでAntiForgeryTokenに問題があります。 ASP.NET MVC 3を使用しています。 jQuery Ajax呼び出しとHtml.AntiForgeryToken() でソリューションを試しました。そのソリューションを使用して、トークンは現在渡されています:
var data = { ... } // with token, key is '__RequestVerificationToken'
$.ajax({
type: "POST",
data: data,
datatype: "json",
traditional: true,
contentType: "application/json; charset=utf-8",
url: myURL,
success: function (response) {
...
},
error: function (response) {
...
}
});
(トークンを含む)データがコントローラーにパラメーターとして渡されるかどうかを確認するために[ValidateAntiForgeryToken]
属性を削除すると、それらが渡されていることがわかります。しかし、何らかの理由で、属性を戻すと、A required anti-forgery token was not supplied or was invalid.
メッセージが表示されます。
何か案は?
編集
偽造防止トークンはフォーム内で生成されていますが、送信アクションを使用して送信していません。代わりに、jqueryを使用してトークンの値を取得し、それを投稿するajaxを試みています。
トークンを含むフォームは次のとおりです。トップマスターページにあります。
<form id="__AjaxAntiForgeryForm" action="#" method="post">
@Html.AntiForgeryToken()
</form>
contentType
をapplication/json
に誤って指定しました。
これがどのように機能するかの例を次に示します。
コントローラ:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(string someValue)
{
return Json(new { someValue = someValue });
}
}
表示:
@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "__AjaxAntiForgeryForm" }))
{
@Html.AntiForgeryToken()
}
<div id="myDiv" data-url="@Url.Action("Index", "Home")">
Click me to send an AJAX request to a controller action
decorated with the [ValidateAntiForgeryToken] attribute
</div>
<script type="text/javascript">
$('#myDiv').submit(function () {
var form = $('#__AjaxAntiForgeryForm');
var token = $('input[name="__RequestVerificationToken"]', form).val();
$.ajax({
url: $(this).data('url'),
type: 'POST',
data: {
__RequestVerificationToken: token,
someValue: 'some value'
},
success: function (result) {
alert(result.someValue);
}
});
return false;
});
</script>
別の(JavaScriptが少ない)アプローチは、私がしたように、このようなものになります:
public static MvcHtmlString AntiForgeryTokenForAjaxPost(this HtmlHelper helper)
{
var antiForgeryInputTag = helper.AntiForgeryToken().ToString();
// Above gets the following: <input name="__RequestVerificationToken" type="hidden" value="PnQE7R0MIBBAzC7SqtVvwrJpGbRvPgzWHo5dSyoSaZoabRjf9pCyzjujYBU_qKDJmwIOiPRDwBV1TNVdXFVgzAvN9_l2yt9-nf4Owif0qIDz7WRAmydVPIm6_pmJAI--wvvFQO7g0VvoFArFtAR2v6Ch1wmXCZ89v0-lNOGZLZc1" />
var removedStart = antiForgeryInputTag.Replace(@"<input name=""__RequestVerificationToken"" type=""hidden"" value=""", "");
var tokenValue = removedStart.Replace(@""" />", "");
if (antiForgeryInputTag == removedStart || removedStart == tokenValue)
throw new InvalidOperationException("Oops! The Html.AntiForgeryToken() method seems to return something I did not expect.");
return new MvcHtmlString(string.Format(@"{0}:""{1}""", "__RequestVerificationToken", tokenValue));
}
__RequestVerificationToken:"P5g2D8vRyE3aBn7qQKfVVVAsQc853s-naENvpUAPZLipuw0pa_ffBf9cINzFgIRPwsf7Ykjt46ttJy5ox5r3mzpqvmgNYdnKc1125jphQV0NnM5nGFtcXXqoY3RpusTH_WcHPzH4S4l1PmB8Uu7ubZBftqFdxCLC5n-xT0fHcAY1"
$(function () {
$("#submit-list").click(function () {
$.ajax({
url: '@Url.Action("SortDataSourceLibraries")',
data: { items: $(".sortable").sortable('toArray'), @Html.AntiForgeryTokenForAjaxPost() },
type: 'post',
traditional: true
});
});
});
そして、それはうまくいくようです!
とても簡単です! HTMLコードで@Html.AntiForgeryToken()
を使用すると、サーバーがこのページに署名し、この特定のページからサーバーに送信される各リクエストには、ハッカーによる偽のリクエストの送信を防ぐためのサインがあります。したがって、このページをサーバーで認証するには、次の2つの手順を実行する必要があります。
1. __RequestVerificationToken
という名前のパラメーターを送信し、その値を取得するには以下のコードを使用します。
<script type="text/javascript">
function gettoken() {
var token = '@Html.AntiForgeryToken()';
token = $(token).val();
return token;
}
</script>
たとえば、ajax呼び出しを行います
$.ajax({
type: "POST",
url: "/Account/Login",
data: {
__RequestVerificationToken: gettoken(),
uname: uname,
pass: pass
},
dataType: 'json',
contentType: 'application/x-www-form-urlencoded; charset=utf-8',
success: successFu,
});
ステップ2は、アクションメソッドを[ValidateAntiForgeryToken]
で装飾するだけです
function DeletePersonel(id){ var data = new FormData(); data.append( "__ RequestVerificationToken "、" @ HtmlHelper.GetAntiForgeryToken() "); $ .ajax({ タイプ: 'POST'、 url: '/ Personel/Delete/'+ id、 data:data、 cache:false、 processData:false、 contentType:false、 success:function( result){ } }); } public static class HtmlHelper { public static string GetAntiForgeryToken() { System.Text.RegularExpressions.Match value = System.Text.RegularExpressions.Regex.Match(System .Web.Helpers.AntiForgery.GetHtml()。T oString()、 "(?:value = \")(。*)(?:\ ")"); if(value.Success) { 戻り値.Groups [1] .Value; } return ""; } }
Asp.Net Coreでは、トークンを直接リクエストできます ドキュメントに記載 :
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@functions{
public string GetAntiXsrfRequestToken()
{
return Xsrf.GetAndStoreTokens(Context).RequestToken;
}
}
そして、JavaScriptでそれを使用します:
function DoSomething(id) {
$.post("/something/todo/"+id,
{ "__RequestVerificationToken": '@GetAntiXsrfRequestToken()' });
}
推奨されるグローバルフィルター、 文書化されているとおり を追加できます。
services.AddMvc(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
})
Asp.Net MVCで@Html.AntiForgeryToken()
を使用すると、Razorは、トークンを保存するために__RequestVerificationToken
という名前の非表示の入力フィールドを作成します。 AJAX実装を作成する場合、このトークンを自分でフェッチし、検証できるようにサーバーにパラメーターとして渡す必要があります。
ステップ1:トークンを取得する
var token = $('input[name="`__RequestVerificationToken`"]').val();
ステップ2:AJAX呼び出しでトークンを渡す
function registerStudent() {
var student = {
"FirstName": $('#fName').val(),
"LastName": $('#lName').val(),
"Email": $('#email').val(),
"Phone": $('#phone').val(),
};
$.ajax({
url: '/Student/RegisterStudent',
type: 'POST',
data: {
__RequestVerificationToken:token,
student: student,
},
dataType: 'JSON',
contentType:'application/x-www-form-urlencoded; charset=utf-8',
success: function (response) {
if (response.result == "Success") {
alert('Student Registered Succesfully!')
}
},
error: function (x,h,r) {
alert('Something went wrong')
}
})
};
注:コンテンツタイプは'application/x-www-form-urlencoded; charset=utf-8'
である必要があります
Githubにプロジェクトをアップロードしました。ダウンロードして試すことができます。
これは古い質問です。しかし、とにかく私の答えを追加して、私のような誰かを助けるかもしれません。
LoggOff
コントローラーのAccounts
メソッドの呼び出しなど、コントローラーの投稿アクションからの結果を処理したくない場合は、次のバージョンの@DarinDimitrovの答えとして実行できます。
@using (Html.BeginForm("LoggOff", "Accounts", FormMethod.Post, new { id = "__AjaxAntiForgeryForm" }))
{
@Html.AntiForgeryToken()
}
<!-- this could be a button -->
<a href="#" id="ajaxSubmit">Submit</a>
<script type="text/javascript">
$('#ajaxSubmit').click(function () {
$('#__AjaxAntiForgeryForm').submit();
return false;
});
</script>
私は多くの回避策を試しましたが、それらのどれも私のために働きませんでした。例外は「必須の偽造防止フォームフィールド "__RequestVerificationToken"でした。
私を助けたのは、フォーム.ajaxを.postに切り替えることでした:
$.post(
url,
$(formId).serialize(),
function (data) {
$(formId).html(data);
});
トークンは、別のコントローラーから提供された場合は機能しません。例えば。ビューがAccounts
コントローラーから返された場合は機能しませんが、POST
からClients
コントローラーに戻ります。
アカウントコントローラーで:
// POST: /Account/SendVerificationCodeSMS
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public JsonResult SendVerificationCodeSMS(string PhoneNumber)
{
return Json(PhoneNumber);
}
ビューで:
$.ajax(
{
url: "/Account/SendVerificationCodeSMS",
method: "POST",
contentType: 'application/x-www-form-urlencoded; charset=utf-8',
dataType: "json",
data: {
PhoneNumber: $('[name="PhoneNumber"]').val(),
__RequestVerificationToken: $('[name="__RequestVerificationToken"]').val()
},
success: function (data, textStatus, jqXHR) {
if (textStatus == "success") {
alert(data);
// Do something on page
}
else {
// Do something on page
}
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(textStatus);
console.log(jqXHR.status);
console.log(jqXHR.statusText);
console.log(jqXHR.responseText);
}
});
contentType
を'application/x-www-form-urlencoded; charset=utf-8'
に設定するか、オブジェクトからcontentType
を単に省略することが重要です...
以下の機能を自由に使用してください。
function AjaxPostWithAntiForgeryToken(destinationUrl, successCallback) {
var token = $('input[name="__RequestVerificationToken"]').val();
var headers = {};
headers["__RequestVerificationToken"] = token;
$.ajax({
type: "POST",
url: destinationUrl,
data: { __RequestVerificationToken: token }, // Your other data will go here
dataType: "json",
success: function (response) {
successCallback(response);
},
error: function (xhr, status, error) {
// handle failure
}
});
}