A2D JS框架 - Web API CSRF保护实现

这次自己实现了类似jQuery中ajax调用的方法,并且针对RESTFul进行了改造和集成,实现的A2D AJAX接口如下: 

$.ajax.RESTFulGetCollection("/api/Users", function (data) { alert(data[5].FirstName); });
$.ajax.RESTFulGetOne("/api/Users/1", function (data) { alert(data.UserID); });
$.ajax.RESTFulDelete("/api/Users/1", function (data) { alert("deleted"); });
$.ajax.RESTFulPost("/api/Users", { UserID: 0, FirstName: "aa", LastName: "bbb"}, function (data) { alert("added"); });
$.ajax.RESTFulPut("/api/Users/1", { UserID: 0, FirstName: "aa", LastName: "bbb"}, function (data) { alert(data); });

 

我们再深入点,要是别人恶意访问Delete的url呢?比如CSRF攻击。普通webform或者普通MVC方式可以比较方便的阻止攻击, 方法参考这篇文章的A8章节

答案:使用http header来传递token。步骤如下(以A2D与ASP.NET WEBAPI配合为例):

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

    $.ajax.Config.CSRFToken="@TokenHeaderValue()";    //把生成的token赋给A2D的ajax

    $.ajax.RESTFulGetCollection("/api/Users", function (data) { alert(data[5].FirstName); });
    $.ajax.RESTFulGetOne("/api/Users/1", function (data) { alert(data.UserID); });
    $.ajax.RESTFulDelete("/api/Users/1", function (data) { alert("deleted"); });
    $.ajax.RESTFulPost("/api/Users", { UserID: 0, FirstName: "aa", LastName: "bbb"}, function (data) { alert("added"); });
    $.ajax.RESTFulPut("/api/Users/1", { UserID: 0, FirstName: "aa", LastName: "bbb"}, function (data) { alert(data); });

 

然后编写webapi的handler:

public class CSRFHandler : DelegatingHandler
    {
        protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            if (request.Method == HttpMethod.Post ||
                request.Method == HttpMethod.Put ||
                request.Method == HttpMethod.Delete)//这里csrf只针对这3种请求才会验证
            {
                ValidateRequestHeader(request);
            }

            return base.SendAsync(request, cancellationToken);
        }


        private void ValidateRequestHeader(HttpRequestMessage request)
        {
            string cookieToken = "";
            string formToken = "";

            IEnumerable<string> tokenHeaders;
            if (request.Headers.TryGetValues("A2D-CSRFToken", out tokenHeaders)) //这个header值要和A2D框架中的一致
            {
                string[] tokens = tokenHeaders.First().Split(':');
                if (tokens.Length == 2)
                {
                    cookieToken = tokens[0].Trim();
                    formToken = tokens[1].Trim();
                }
            }
            AntiForgery.Validate(cookieToken, formToken);
        }
    }

 

最后在WebApiConfig中注册这个handler

public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.MessageHandlers.Add(new CSRFHandler());

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }

 

好了,都搞定了。

code download.

 

 

 

posted @ 2013-08-12 19:41  McKay  阅读(2466)  评论(1编辑  收藏  举报