The fake form field "__RequestVerificationToken" is missing when using jQuery Ajax and Html.AntiForgeryToken ()

I applied the Razor equivalent to the solution described in the accepted answer to this question: jQuery Ajax calls and Html.AntiForgeryToken () But I kept getting the following exception:

System.Web.Mvc.HttpAntiForgeryException (0x80004005): An anti-fake field of the form "__RequestVerificationToken" is not required.

change

I managed to get around this:

function AddAntiForgeryToken(data) { data.append('__RequestVerificationToken',$('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val()); return data; }; function CallAjax(url, type, data, success, error) { var ajaxOptions = { url: url, type: type, contentType: 'application/json'}; if (type == 'POST') { var fd = new window.FormData(); fd = AddAntiForgeryToken(fd); $.each(data, function (i, n) { fd.append(i,n); }); data = fd; ajaxOptions.processData = false; ajaxOptions.contentType = false; } ajaxOptions.data = data; if (success) ajaxOptions.success = success; //If there is a custom error handler nullify the general statusCode setting. if (error) { ajaxOptions.error = error; ajaxOptions.statusCode = null; }; $.ajax(ajaxOptions); } 

But, unfortunately, FormData () formats are supported only in the latest browser versions. Any workaround that may work before FormData (), as introduced?

change I wonder why the ValidateAntiForgeryTokenAttribute searches for the AntyForgeryToken only in the form data and does not look for it in the route values, as you can see below in the code of the closed classes AntiForgeryTokenStore and AntiForgeryWorker?

 public void Validate(HttpContextBase httpContext) { this.CheckSSLConfig(httpContext); AntiForgeryToken cookieToken = this._tokenStore.GetCookieToken(httpContext); AntiForgeryToken formToken = this._tokenStore.GetFormToken(httpContext); this._validator.ValidateTokens(httpContext, AntiForgeryWorker.ExtractIdentity(httpContext), cookieToken, formToken); } public AntiForgeryToken GetFormToken(HttpContextBase httpContext) { string serializedToken = httpContext.Request.Form[this._config.FormFieldName]; if (string.IsNullOrEmpty(serializedToken)) return (AntiForgeryToken) null; else return this._serializer.Deserialize(serializedToken); } 
+6
source share
3 answers

Well, after digging a few more I found a good solution for my problem in this link: ASP.NET MVC Ajax CSRF Protection with jQuery 1.5

As far as I understand, the solution described in the selected answer to this question: jQuery Ajax calls and Html.AntiForgeryToken () should not work (I really did not succeed).

+4
source

Create antiforgerytoken:

 @using (Html.BeginForm()) { @Html.AntiForgeryToken() <input ...> } 

Create a function to add a token to the ajax request:

 function addRequestVerificationToken(data) { data.__RequestVerificationToken=$('input[name=__RequestVerificationToken]').val(); return data; }; 

Then you can use it as follows:

 $.ajax({ type: "POST", url: '@Url.Action("MyMethod", "MyController", new {area = "MyArea"})', dataType: "json", traditional: true, data: addRequestVerificationToken( { "id": "12345678" } ); }) .done(function(result) { if (result) { // Do something } else { // Log or show an error message } return false; }); 
+1
source

When you call CallAjax() , where does the data come from? I ask because, as a rule, when your data comes from the form, your CSRF token is already part of the form, usually in a hidden field.

 <form action="yourPage.html" method="POST"> <input type="hidden" name="__RequestVerificationToken" value="......"/> .... other form fields .... </form> 

So, if your data comes from a form, you just need to make sure that the token is a hidden part of this form, and the token should be automatically included.

If your data comes from somewhere other than the form, then it’s clear that you somewhere sealed your token, and then turned it on after collecting the data. But you might consider adding a token to the data, instead of creating a new object from the token, and then adding all the data to it.

 if (type == 'POST') { data._RequestVerificationToken = $("input[name='__RequestVerificationToken']").val(); ajaxOptions.processData = false; ajaxOptions.contentType = false; } 
0
source

Source: https://habr.com/ru/post/946014/


All Articles