include antiforgerytoken in ajax post ASP.NET MVC

后端 未结 11 2268
感动是毒
感动是毒 2020-11-22 14:00

I am having trouble with the AntiForgeryToken with ajax. I\'m using ASP.NET MVC 3. I tried the solution in jQuery Ajax calls and the Html.AntiForgeryToken(). Using that solu

相关标签:
11条回答
  • 2020-11-22 14:26

    In Asp.Net MVC when you use @Html.AntiForgeryToken() Razor creates a hidden input field with name __RequestVerificationToken to store tokens. If you want to write an AJAX implementation you have to fetch this token yourself and pass it as a parameter to the server so it can be validated.

    Step 1: Get the token

    var token = $('input[name="`__RequestVerificationToken`"]').val();
    

    Step 2: Pass the token in the AJAX call

    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: The content type should be 'application/x-www-form-urlencoded; charset=utf-8'

    I have uploaded the project on Github; you can download and try it.

    https://github.com/lambda2016/AjaxValidateAntiForgeryToken

    0 讨论(0)
  • 2020-11-22 14:30

    I tried a lot of workarrounds and non of them worked for me. The exception was "The required anti-forgery form field "__RequestVerificationToken" .

    What helped me out was to switch form .ajax to .post:

    $.post(
        url,
        $(formId).serialize(),
        function (data) {
            $(formId).html(data);
        });
    
    0 讨论(0)
  • 2020-11-22 14:31

    In Asp.Net Core you can request the token directly, as documented:

    @inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf    
    @functions{
        public string GetAntiXsrfRequestToken()
        {
            return Xsrf.GetAndStoreTokens(Context).RequestToken;
        }
    }
    

    And use it in javascript:

    function DoSomething(id) {
        $.post("/something/todo/"+id,
                   { "__RequestVerificationToken": '@GetAntiXsrfRequestToken()' });
    }
    

    You can add the recommended global filter, as documented:

    services.AddMvc(options =>
    {
        options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
    })
    

    Update

    The above solution works in scripts that are part of the .cshtml. If this is not the case then you can't use this directly. My solution was to use a hidden field to store the value first.

    My workaround, still using GetAntiXsrfRequestToken:

    When there is no form:

    <input type="hidden" id="RequestVerificationToken" value="@GetAntiXsrfRequestToken()">
    

    The name attribute can be omitted since I use the id attribute.

    Each form includes this token. So instead of adding yet another copy of the same token in a hidden field, you can also search for an existing field by name. Please note: there can be multiple forms inside a document, so name is in that case not unique. Unlike an id attribute that should be unique.

    In the script, find by id:

    function DoSomething(id) {
        $.post("/something/todo/"+id,
           { "__RequestVerificationToken": $('#RequestVerificationToken').val() });
    }
    

    An alternative, without having to reference the token, is to submit the form with script.

    Sample form:

    <form id="my_form" action="/something/todo/create" method="post">
    </form>
    

    The token is automatically added to the form as a hidden field:

    <form id="my_form" action="/something/todo/create" method="post">
    <input name="__RequestVerificationToken" type="hidden" value="Cf..." /></form>
    

    And submit in the script:

    function DoSomething() {
        $('#my_form').submit();
    }
    

    Or using a post method:

    function DoSomething() {
        var form = $('#my_form');
    
        $.post("/something/todo/create", form.serialize());
    }
    
    0 讨论(0)
  • 2020-11-22 14:31

    Feel free to use the function below:

    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
        }
    });
    

    }

    0 讨论(0)
  • 2020-11-22 14:32

    The token won't work if it was supplied by a different controller. E.g. it won't work if the view was returned by the Accounts controller, but you POST to the Clients controller.

    0 讨论(0)
  • 2020-11-22 14:39
    
    
            function DeletePersonel(id) {
    
                    var data = new FormData();
                    data.append("__RequestVerificationToken", "@HtmlHelper.GetAntiForgeryToken()");
    
                    $.ajax({
                        type: '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().ToString(), "(?:value=\")(.*)(?:\")");
                    if (value.Success)
                    {
                        return value.Groups[1].Value;
                    }
                    return "";
                }
            }
    
    0 讨论(0)
提交回复
热议问题