jQuery Ajax calls and the Html.AntiForgeryToken()

前端 未结 20 2388
鱼传尺愫
鱼传尺愫 2020-11-22 16:34

I have implemented in my app the mitigation to CSRF attacks following the informations that I have read on some blog post around the internet. In particular these post have

相关标签:
20条回答
  • 2020-11-22 17:22

    first use @Html.AntiForgeryToken() in html

     $.ajax({
            url: "@Url.Action("SomeMethod", "SomeController")",
            type: 'POST',
            data: JSON.stringify(jsonObject),
            contentType: 'application/json; charset=utf-8',
            dataType: 'json',
            async: false,
            beforeSend: function (request) {
                request.setRequestHeader("RequestVerificationToken", $("[name='__RequestVerificationToken']").val());
            },
            success: function (msg) {
                alert(msg);
            }
    
    0 讨论(0)
  • 2020-11-22 17:23

    I know there are a lot of other answers, but this article is nice and concise and forces you to check all of your HttpPosts, not just some of them:

    http://richiban.wordpress.com/2013/02/06/validating-net-mvc-4-anti-forgery-tokens-in-ajax-requests/

    It uses HTTP headers instead of trying to modify the form collection.

    Server

    //make sure to add this to your global action filters
    [AttributeUsage(AttributeTargets.Class)]
    public class ValidateAntiForgeryTokenOnAllPosts : AuthorizeAttribute
    {
        public override void OnAuthorization( AuthorizationContext filterContext )
        {
            var request = filterContext.HttpContext.Request;
    
            //  Only validate POSTs
            if (request.HttpMethod == WebRequestMethods.Http.Post)
            {
                //  Ajax POSTs and normal form posts have to be treated differently when it comes
                //  to validating the AntiForgeryToken
                if (request.IsAjaxRequest())
                {
                    var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];
    
                    var cookieValue = antiForgeryCookie != null
                        ? antiForgeryCookie.Value 
                        : null;
    
                    AntiForgery.Validate(cookieValue, request.Headers["__RequestVerificationToken"]);
                }
                else
                {
                    new ValidateAntiForgeryTokenAttribute()
                        .OnAuthorization(filterContext);
                }
            }
        }
    }
    

    Client

    var token = $('[name=__RequestVerificationToken]').val();
    var headers = {};
    headers["__RequestVerificationToken"] = token;
    
    $.ajax({
        type: 'POST',
        url: '/Home/Ajax',
        cache: false,
        headers: headers,
        contentType: 'application/json; charset=utf-8',
        data: { title: "This is my title", contents: "These are my contents" },
        success: function () {
            ...
        },
        error: function () {
            ...
        }
    });
    
    0 讨论(0)
  • 2020-11-22 17:23

    You can do this also:

    $("a.markAsDone").click(function (event) {
        event.preventDefault();
    
        $.ajax({
            type: "post",
            dataType: "html",
            url: $(this).attr("rel"),
            data: $('<form>@Html.AntiForgeryToken()</form>').serialize(),
            success: function (response) {
            // ....
            }
        });
    });
    

    This is using Razor, but if you're using WebForms syntax you can just as well use <%= %> tags

    0 讨论(0)
  • 2020-11-22 17:26

    The Solution i found is not for ASPX but for Razor, but quite comperable issue.

    I resolved it by adding the AntiForgery to the request. The HTML Helper does not create a HTML id with the call

    @Html.AntiForgeryToken()
    

    In order to add the token to the postrequest i just added the AntiForgery id to the hidden field with jquery:

    $("input[name*='__RequestVerificationToken']").attr('id', '__AjaxAntiForgeryForm');
    

    This caused the controller to accept the request with the [ValidateAntiForgeryToken] attribute

    0 讨论(0)
  • 2020-11-22 17:27

    found this very clever idea from https://gist.github.com/scottrippey/3428114 for every $.ajax calls it modifies the request and add the token.

    // Setup CSRF safety for AJAX:
    $.ajaxPrefilter(function(options, originalOptions, jqXHR) {
        if (options.type.toUpperCase() === "POST") {
            // We need to add the verificationToken to all POSTs
            var token = $("input[name^=__RequestVerificationToken]").first();
            if (!token.length) return;
    
            var tokenName = token.attr("name");
    
            // If the data is JSON, then we need to put the token in the QueryString:
            if (options.contentType.indexOf('application/json') === 0) {
                // Add the token to the URL, because we can't add it to the JSON data:
                options.url += ((options.url.indexOf("?") === -1) ? "?" : "&") + token.serialize();
            } else if (typeof options.data === 'string' && options.data.indexOf(tokenName) === -1) {
                // Append to the data string:
                options.data += (options.data ? "&" : "") + token.serialize();
            }
        }
    });
    
    0 讨论(0)
  • 2020-11-22 17:27

    1.Define Function to get Token from server

    @function
    {
    
            public string TokenHeaderValue()
            {
                string cookieToken, formToken;
                AntiForgery.GetTokens(null, out cookieToken, out formToken);
                return cookieToken + ":" + formToken;                
            }
    }
    

    2.Get token and set header before send to server

    var token = '@TokenHeaderValue()';    
    
           $http({
               method: "POST",
               url: './MainBackend/MessageDelete',
               data: dataSend,
               headers: {
                   'RequestVerificationToken': token
               }
           }).success(function (data) {
               alert(data)
           });
    

    3. Onserver Validation on HttpRequestBase on method you handle Post/get

            string cookieToken = "";
            string formToken = "";
            string[] tokens = Request.Headers["RequestVerificationToken"].Split(':');
                if (tokens.Length == 2)
                {
                    cookieToken = tokens[0].Trim();
                    formToken = tokens[1].Trim();
                }
            AntiForgery.Validate(cookieToken, formToken);
    
    0 讨论(0)
提交回复
热议问题