How to send AntiForgeryToken (CSRF) along with FormData via jquery ajax

So I want to POST fileUpload along with AntiForgeryToken via AJAX. Here is my code:

View

 @using (Html.BeginForm("Upload", "RX", FormMethod.Post, new {id = "frmRXUpload", enctype = "multipart/form-data"})) { @Html.AntiForgeryToken() @Html.TextBoxFor(m => m.RXFile, new {.type = "file"}) ...rest of code here } <script> $(document).ready(function(){ $('#btnRXUpload').click(function () { var form = $('#frmRXUpload') if (form.valid()) { var formData = new FormData(form); formData.append('files', $('#frmRXUpload input[type="file"]')[0].files[0]); formData.append('__RequestVerificationToken', fnGetToken()); $.ajax({ type: 'POST', url: '/RX/Upload', data: formData, contentType: false, processData: false }) } }) }) </script> 

controller

 [HttpPost] [ValidateAntiForgeryToken] public ActionResult Upload() { //rest of code here } 

I get

The fake ban cannot be decrypted. If this application is hosted by a web farm or cluster

error with the help of a violinist. Any idea how to solve this problem?

I FOUND THE ANSWER:

 <script> $(document).ready(function(){ $('#btnRXUpload').click(function () { var form = $('#frmRXUpload') if (form.valid()) { var formData = new FormData(form.get(0)); //add .get(0) formData.append('files', $('#frmRXUpload input[type="file"]')[0].files[0]); $.ajax({ type: 'POST', url: '/RX/Upload', data: formData, contentType: false, processData: false }) } }) }) </script> 
+5
source share
2 answers

FINALLY FOUND ANSWER:

I just need to add .get(0) to the form, here is the code:

 <script> $(document).ready(function(){ $('#btnRXUpload').click(function () { var form = $('#frmRXUpload') if (form.valid()) { var formData = new FormData(form.get(0)); //add .get(0) formData.append('files', $('#frmRXUpload input[type="file"]')[0].files[0]); //formData.append('__RequestVerificationToken', fnGetToken()); //remark this line $.ajax({ type: 'POST', url: '/RX/Upload', data: formData, contentType: false, processData: false }) } }) }) </script> 
+4
source

You need to add the token to the request headers, not to the form. Like this:

  if (form.valid()) { var formData = new FormData(form); formData.append('files', $('#frmRXUpload input[type="file"]')[0].files[0]); $.ajax({ type: 'POST', url: '/RX/Upload', data: formData, contentType: 'multipart/form-data', processData: false, headers: { '__RequestVerificationToken': fnGetToken() } }) } 

Edit Looking back, as I myself solved this problem, I remember that the standard ValidateAntiForgeryTokenAttribute file looks in the Request.Form object, which is not always populated for an AJAX request. (In your case, the content type multipart/form-data is required to download the file, whereas application/x-www-form-urlencoded is required for the form column for the CSRF token. You set contentType=false , but conflicting content types are required for two operations, which may be part of your problem). So, to check the token on the server, you will need to write a custom attribute for your action method, which checks the token in the request header:

 public sealed class ValidateJsonAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter { public void OnAuthorization(AuthorizationContext filterContext) { if (filterContext == null) { throw new ArgumentNullException("filterContext"); } var httpContext = filterContext.HttpContext; var cookie = httpContext.Request.Cookies[AntiForgeryConfig.CookieName]; AntiForgery.Validate(cookie != null ? cookie.Value : null, httpContext.Request.Headers["__RequestVerificationToken"]); } } 

More info (a bit dated) here .

+3
source

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


All Articles