Ich habe Probleme mit dem AntiForgeryToken mit Ajax. Ich verwende ASP.NET MVC 3. Ich habe die Lösung in jQuery Ajax-Aufrufen und dem Html.AntiForgeryToken () versucht. Mit dieser Lösung wird das Token nun übergeben:
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) {
...
}
});
Wenn ich das [ValidateAntiForgeryToken]
-Attribut entferne, nur um zu sehen, ob die Daten (mit dem Token) als Parameter an den Controller übergeben werden, kann ich sehen, dass sie übergeben werden. Aber aus irgendeinem Grund wird die A required anti-forgery token was not supplied or was invalid.
-Nachricht immer noch angezeigt, wenn ich das Attribut zurücksetze.
Irgendwelche Ideen?
EDIT
Das Antiforgerytoken wird in einem Formular generiert, aber ich übermittle es nicht mit einer Submit-Aktion. Stattdessen bekomme ich nur den Wert des Tokens, indem ich jquery verwende und dann versuche, das zu posten.
Hier ist das Formular, das das Token enthält und sich auf der obersten Masterseite befindet:
<form id="__AjaxAntiForgeryForm" action="#" method="post">
@Html.AntiForgeryToken()
</form>
Sie haben die contentType
falsch in application/json
angegeben.
Hier ist ein Beispiel, wie das funktionieren könnte.
Regler:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(string someValue)
{
return Json(new { someValue = someValue });
}
}
Aussicht:
@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>
Ein anderer (weniger Javascript) -Ansatz, den ich gemacht habe, geht in etwa so
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
});
});
});
Und es scheint zu funktionieren!
es ist so einfach! Wenn Sie @Html.AntiForgeryToken()
in Ihrem HTML-Code verwenden, bedeutet dies, dass der Server diese Seite signiert hat und jede Anforderung, die von dieser bestimmten Seite an den Server gesendet wird, ein Zeichen enthält, das verhindert, dass Hacker eine gefälschte Anforderung senden. Damit diese Seite vom Server authentifiziert werden kann, müssen Sie zwei Schritte ausführen:
1.Senden Sie einen Parameter mit dem Namen __RequestVerificationToken
und erhalten Sie den folgenden Wert für die Verwendung von Codes:
<script type="text/javascript">
function gettoken() {
var token = '@Html.AntiForgeryToken()';
token = $(token).val();
return token;
}
</script>
nehmen Sie zum Beispiel einen Ajax-Anruf
$.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,
});
und Schritt 2 schmücken Sie einfach Ihre Aktionsmethode mit [ValidateAntiForgeryToken]
Funktion DeletePersonel (id) { var data = new FormData (); data.append ("__ RequestVerificationToken", "@ HtmlHelper.GetAntiForgeryToken ()"); $ .ajax ({ Typ: 'POST', URL: '/ Personel/Delete /' + ID, Daten: Daten, Cache: falsch, Prozessdaten: Falsch, contentType: false, success: Funktion (Ergebnis) { } }); } öffentliche statische Klasse HtmlHelper { öffentliche statische Zeichenfolge GetAntiForgeryToken () { System.Text.RegularExpressions.Match value = System.Text.RegularExpressions.Regex.Match (System.Web.Helpers.AntiForgery.GetHtml (). ToString (), "(?: Value = \") (. *) (?). :\")"); if (value.Success) { Rückgabewert.Gruppen [1] .Value; } Rückkehr ""; } }
In Asp.Net Core können Sie das Token direkt anfordern, wie dokumentiert :
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@functions{
public string GetAntiXsrfRequestToken()
{
return Xsrf.GetAndStoreTokens(Context).RequestToken;
}
}
Und benutze es in Javascript:
function DoSomething(id) {
$.post("/something/todo/"+id,
{ "__RequestVerificationToken": '@GetAntiXsrfRequestToken()' });
}
Sie können den empfohlenen globalen Filter hinzufügen wie dokumentiert :
services.AddMvc(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
})
Wenn Sie in Asp.Net MVC @Html.AntiForgeryToken()
verwenden, erstellt Razor ein verstecktes Eingabefeld mit dem Namen __RequestVerificationToken
zum Speichern von Token. Wenn Sie eine AJAX -Implementierung schreiben möchten, müssen Sie dieses Token selbst abrufen und als Parameter an den Server übergeben, damit es überprüft werden kann.
Schritt 1: Holen Sie sich das Token
var token = $('input[name="`__RequestVerificationToken`"]').val();
Schritt 2: Übergeben Sie das Token beim Aufruf von 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')
}
})
};
Note: Der Inhaltstyp sollte 'application/x-www-form-urlencoded; charset=utf-8'
sein.
Ich habe das Projekt auf Github hochgeladen. Sie können es herunterladen und ausprobieren.
Ich weiß, das ist eine alte Frage. Aber ich werde meine Antwort trotzdem hinzufügen, könnte jemandem wie mir helfen.
Wenn Sie das Ergebnis der Nachaktion des Controllers nicht verarbeiten möchten, z. B. das Aufrufen der LoggOff
-Methode des Accounts
-Controllers, können Sie die folgende Version der Antwort von @DarinDimitrov ausführen:
@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>
Ich habe viele Workarounds ausprobiert und keiner von ihnen hat für mich gearbeitet. Die Ausnahme war "Das erforderliche Anti-Fälschungs-Formularfeld" __RequestVerificationToken ".
Was mir geholfen hat, war, von .ajax zu .post zu wechseln:
$.post(
url,
$(formId).serialize(),
function (data) {
$(formId).html(data);
});
Das Token funktioniert nicht, wenn es von einem anderen Controller geliefert wurde. Z.B. Es funktioniert nicht, wenn die Ansicht vom Controller Accounts
zurückgegeben wurde, aber Sie POST
zum Controller Clients
.
In Account Controller:
// POST: /Account/SendVerificationCodeSMS
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public JsonResult SendVerificationCodeSMS(string PhoneNumber)
{
return Json(PhoneNumber);
}
Im Hinblick auf:
$.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);
}
});
Es ist wichtig, contentType
auf 'application/x-www-form-urlencoded; charset=utf-8'
zu setzen oder einfach contentType
von dem Objekt wegzulassen ...
Fühlen Sie sich frei, die folgende Funktion zu verwenden:
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
}
});
}