我有一个由 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 theAntiForgeryToken
.
@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 theif (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/