c# - AngularJS Web Api AntiForgeryToken CSRF

标签 c# angularjs asp.net-mvc asp.net-web-api

我有一个由 ASP.NET MVC 应用程序托管的 AngularJS 单页应用程序 (SPA)。
后端是 ASP.NET Web Api

我想通过在 ASP.NET MVC 部分生成一个 AntiForgeryToken 来保护它免受 CSRF 攻击,将它传递给 >AngularJS,然后让 Web Api 验证从后续 AngularJS 调用中收到的 AntiForgeryToken

“Cross-Site Request Forgery (CSRF) is an attack that forces an end user to execute unwanted actions on a web application in which they're currently authenticated. CSRF attacks specifically target state-changing requests, not theft of data, since the attacker has no way to see the response to the forged request. With a little help of social engineering (such as sending a link via email or chat), an attacker may trick the users of a web application into executing actions of the attacker's choosing. If the victim is a normal user, a successful CSRF attack can force the user to perform state changing requests like transferring funds, changing their email address, and so forth. If the victim is an administrative account, CSRF can compromise the entire web application.”
- Open Web Application Security Project (OWASP)

最佳答案

Add to the ASP.NET MVC View that serves the AngularJS SPA, let's say Views\Home\Index.cshtml, the HTML helper that generates the AntiForgeryToken.

@Html.AntiForgeryToken();

Configure AngularJS to pass the above generated AntiForgeryToken as Request Header.

angular.module('app')
.run(function ($http) {
    $http.defaults.headers.common['X-XSRF-Token'] =
        angular.element('input[name="__RequestVerificationToken"]').attr('value');
});

Create a custom Web API Filter to validate all non-GET requests (PUT, PATCH, POST, DELETE).

This assumes that all your GET requests are safe and don't need protecting.
If that's not the case, remove the if (actionContext.Request.Method.Method != "GET") exclusion.

using System;
using System.Linq;
using System.Net.Http;
using System.Web.Helpers;
using System.Web.Http.Filters;

namespace Care.Web.Filters
{
    public sealed class WebApiValidateAntiForgeryTokenAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(
            System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            if (actionContext == null)
            {
                throw new ArgumentNullException("actionContext");
            }

            if (actionContext.Request.Method.Method != "GET")
            {
                var headers = actionContext.Request.Headers;
                var tokenCookie = headers
                    .GetCookies()
                    .Select(c => c[AntiForgeryConfig.CookieName])
                    .FirstOrDefault();

                var tokenHeader = string.Empty;
                if (headers.Contains("X-XSRF-Token"))
                {
                    tokenHeader = headers.GetValues("X-XSRF-Token").FirstOrDefault();
                }

                AntiForgery.Validate(
                    tokenCookie != null ? tokenCookie.Value : null, tokenHeader);
            }

            base.OnActionExecuting(actionContext);
        }
    }
}

Register the newly created filter as a global one, in Global.asax.cs.

    private static void RegisterWebApiFilters(HttpFilterCollection filters)
    {
        filters.Add(new WebApiValidateAntiForgeryTokenAttribute());
    }

或者,如果您不想在全局范围内添加此过滤器,您可以只将它放在特定的 Web API 操作上,就像这样

[WebApiValidateAntiForgeryToken]

当然,这在定义上是不安全的,因为您总是有可能忘记将该属性应用于需要它的操作。

另请注意,您必须拥有 Microsoft.AspNet.WebApi.Core 程序包才能访问 System.Web.Http 命名空间。您可以使用 Install-Package Microsoft.AspNet.WebApi.Core 通过 NuGet 安装它。

这篇文章很大程度上受到了 this blog post 的启发。 .

关于c# - AngularJS Web Api AntiForgeryToken CSRF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32460196/

相关文章:

c# - 基本 MVC View 将模型属性返回为 null

asp.net-mvc - 在 ASP.NET mvc 中使用 Session 变量仍然可以,或者对于某些东西(比如购物车)有更好的选择吗

html - ng-show 指令仅在设备上返回正确但为空的 <img>

c# - 扩展 HtmlHelper 类 asp.net mvc4

c# - 在多个链式 LINQ 查询中使用一个变量

c# Reflection - 查找集合的通用类型

javascript - 当我直接粘贴 URL 时,AngularJs View 不会加载

javascript - 使用 Protractor 测试时如何找到 ng-repeater 的最后一个元素

c# - 使用 Entity Framework 进行 MVC 4 条件模型验证

c# - 检查对象是否为 System.Generic.List<T>,对于任何 T