Enable Antiforgery Token with ASP.NET Core and JQuery

后端 未结 5 2118
鱼传尺愫
鱼传尺愫 2020-12-15 06:40

I am using JQuery with ASP.NET Core 1.0.1 and I have the Ajax call:

$(\"#send-message\").on(\"submit\", function (event) {
  event.preventDefault();
  var $f         


        
相关标签:
5条回答
  • 2020-12-15 06:56

    You can register a global ajax event that will add the header to all ajax calls that are not GET by this:

    $(document).ajaxSend(function(e, xhr, options) {
        if (options.type.toUpperCase() != "GET") {
            xhr.setRequestHeader("RequestVerificationToken", token);
        }
    });
    
    0 讨论(0)
  • 2020-12-15 06:56

    In addition to ygoe's answer, if you want to pass a XSRF token as a header, e.g. X-XSRF-Token:

    var ajax = {
        url: "/users",
        data: data,
        type: "post",
    
        // ...
    };
    
    var antiForgeryToken = $("input[name=__RequestVerificationToken]").val();
    if (antiForgeryToken) {
        ajax.headers = {};
        ajax.headers["X-XSRF-Token"] = antiForgeryToken;
    };
    
    $.ajax(ajax);
    

    then you will also need to specify the respective antiforgery option:

    public void ConfigureServices(IServiceCollection services)
    {
        // your services to inject are also configured here ...
    
        services.AddAntiforgery(options => options.HeaderName = "X-XSRF-Token");
        services.AddMvc();
    }
    

    Then you can use the standard ValidateAntiForgeryToken attribute to validate the request:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public JsonResult Users(UserModel user)
    {
        // ...
    }
    
    0 讨论(0)
  • 2020-12-15 06:59

    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());
    })
    
    0 讨论(0)
  • 2020-12-15 07:12

    mode777's answer just needs a small addition to make this work (I tried it):

    $(document).ajaxSend(function(e, xhr, options) {
        if (options.type.toUpperCase() == "POST") {
            var token = $form.find("input[name='af_token']").val();
            xhr.setRequestHeader("RequestVerificationToken", token);
        }
    });
    

    Actually, if you also submit using Ajax, you don't need to use a form at all. Put this in your _layout:

     <span class="AntiForge"> @Html.AntiForgeryToken() </span>
    

    Then you pickup the token by adding this to your javascript:

    $(document)
       .ajaxSend(function (event, jqxhr, settings) {
            if (settings.type.toUpperCase() != "POST") return;
            jqxhr.setRequestHeader('RequestVerificationToken', $(".AntiForge" + " input").val())
    })
    

    The @HtmlAntiForgeryToken generates a hidden input field with the antiforgery token, the same as when using a form. The code above finds it using the class selector to select the span, then gets the input field inside that to collect the token and add it as a header.

    0 讨论(0)
  • 2020-12-15 07:17

    Note: This answer applies to ASP.NET Core 2.0. It may not fit to older versions.

    Here's what I've done after digging through aspnet's source code for a short while:

    public static class HttpContextExtensions
    {
        public static string GetAntiforgeryToken(this HttpContext httpContext)
        {
            var antiforgery = (IAntiforgery)httpContext.RequestServices.GetService(typeof(IAntiforgery));
            var tokenSet = antiforgery.GetAndStoreTokens(httpContext);
            string fieldName = tokenSet.FormFieldName;
            string requestToken = tokenSet.RequestToken;
            return requestToken;
        }
    }
    

    You can use it in a view like this:

    <script>
        var data = {
            yourData: "bla",
            "__RequestVerificationToken": "@Context.GetAntiforgeryToken()"
        };
        $.post("@Url.Action("ActionName")", data);
    </script>
    

    You might modify the extension method to return the name of the field as well, in any form you wish, e. g. a JSON fragment.

    0 讨论(0)
提交回复
热议问题