ValidateAntiForgeryToken with SPA architecture

后端 未结 4 1425
南旧
南旧 2020-12-24 04:07

I am trying to set Register and Login for Hot Towel SPA applicantion. I have created SimpleMembershipFilters and ValidateHttpAntiForgeryTokenAttribute based on the asp.net s

4条回答
  •  臣服心动
    2020-12-24 04:26

    I would read this article on how to use antiforgery tokens using javascript. The article is written for WebApi but it can easily applied to an MVC controller if you want to.

    The short answer is something like this: Inside your cshtml view:

    
    

    Then inside your asp.net controller you need to validate the token like so:

    void ValidateRequestHeader(HttpRequestMessage request)
    {
        string cookieToken = "";
        string formToken = "";
    
        IEnumerable tokenHeaders;
        if (request.Headers.TryGetValues("RequestVerificationToken", out tokenHeaders))
        {
            string[] tokens = tokenHeaders.First().Split(':');
            if (tokens.Length == 2)
            {
                cookieToken = tokens[0].Trim();
                formToken = tokens[1].Trim();
            }
        }
        AntiForgery.Validate(cookieToken, formToken);
    }
    

    The reason you want to pass it in the headers is because if you pass it as a parameter data parameter in your ajax call, inside the querystring or body, of the request. Then it will be harder for you to get the antiforgery token for all your different scenarios. Because you will have to deserialize the body and then find the token. In the headers its pretty consistent and easy to retrieve.


    ****edit for ray**

    Here is an example of an action filter which you can use to attribute web api methods to validate if a antiforgerytoken is provided.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Helpers;
    using System.Web.Http.Filters;
    using System.Net.Http;
    using System.Net;
    using System.Threading.Tasks;
    using System.Web.Http.Controllers;
    using System.Threading;
    
    namespace PAWS.Web.Classes.Filters
    {
        public class ValidateJsonAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter
        {
            public Task ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func> continuation)
            {
                if (actionContext == null)
                {
                    throw new ArgumentNullException("HttpActionContext");
                }
    
                if (actionContext.Request.Method != HttpMethod.Get)
                {
                    return ValidateAntiForgeryToken(actionContext, cancellationToken, continuation);
                }
    
                return continuation();
            }
    
            private Task FromResult(HttpResponseMessage result)
            {
                var source = new TaskCompletionSource();
                source.SetResult(result);
                return source.Task;
            }
    
            private Task ValidateAntiForgeryToken(HttpActionContext actionContext, CancellationToken cancellationToken, Func> continuation)
            {
                try
                {
                    string cookieToken = "";
                    string formToken = "";
                    IEnumerable tokenHeaders;
                    if (actionContext.Request.Headers.TryGetValues("RequestVerificationToken", out tokenHeaders))
                    {
                        string[] tokens = tokenHeaders.First().Split(':');
                        if (tokens.Length == 2)
                        {
                            cookieToken = tokens[0].Trim();
                            formToken = tokens[1].Trim();
                        }
                    }
                    AntiForgery.Validate(cookieToken, formToken);
                }
                catch (System.Web.Mvc.HttpAntiForgeryException ex)
                {
                    actionContext.Response = new HttpResponseMessage
                    {
                        StatusCode = HttpStatusCode.Forbidden,
                        RequestMessage = actionContext.ControllerContext.Request
                    };
                    return FromResult(actionContext.Response);
                }
                return continuation();
            }
        }
    }
    

提交回复
热议问题