Angular2 ASP.NET Core AntiForgeryToken
Angular2 ASP.NET Core AntiForgeryToken
我有一个 Angular2 应用程序。在ASP.NET5(Core).
内是运行
它对工作正常的控制器进行 Http 调用。
但现在我需要建立跨站脚本投影。
如何在每个 Http 请求上生成一个新令牌,然后在 Angular2 个应用中执行 AntiForgeryToken 检查?
注意:我在 Angular 中的数据表单不是从 MVC 视图生成的,而是完全用 Angular2 编写的,并且仅调用 Web 服务。
我看到的所有示例都已过时并且无法正常工作/无法完全正常工作。
我如何在 Angular2 中集成 AntiForgeryToken 检查以对抗 ASP.NET 5 其中表单是纯 Angular?
谢谢。
我认为您需要制作支持通过 header 而不是表单值发送令牌的自定义 AntiForgeryValidationToken 属性。然后将令牌添加到从 Angular2 应用程序到 api 的每个请求的 header。这里的例子 How do you set global custom headers in Angular2?
要验证来自 header 的令牌,您可以使用如下方法:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public sealed class ValidateHeaderAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException(nameof(filterContext));
}
var httpContext = filterContext.HttpContext;
if (httpContext.Request.Headers["__RequestVerificationToken"] == null)
{
httpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
httpContext.Response.StatusDescription = "RequestVerificationToken missing.";
filterContext.Result = new JsonResult
{
Data = new { ErrorMessage = httpContext.Response.StatusDescription },
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
return;
}
var cookie = httpContext.Request.Cookies[System.Web.Helpers.AntiForgeryConfig.CookieName];
System.Web.Helpers.AntiForgery.Validate(cookie != null ? cookie.Value : null, httpContext.Request.Headers["__RequestVerificationToken"]);
}
}
然后您只需在控制器中的方法上添加 [ValidateHeaderAntiForgeryToken]。但请注意,这是来自 MVC 5,ASP.NET 4.5.2 项目,因此您可能需要稍微更改它以适应 .NET Core。此外,我将其修改为 return 如果令牌丢失,结果为 JSON ,如果您不处理错误响应并将其输出给用户,则可以删除该部分。
此属性核心部分的学分转到:https://nozzlegear.com/blog/send-and-validate-an-asp-net-antiforgerytoken-as-a-request-header
困难的部分是如何在纯 Angular 2 应用程序(无法访问 .cshtml 文件)中不使用 @Html.AntiForgeryToken()
来生成 AntiForgeryToken。我也在寻找答案。
我正在使用操作过滤器发送请求令牌。
只需将其应用于您想要新防伪令牌的操作,例如Angular2 SPA、WebAPI 操作等
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class AngularAntiForgeryTokenAttribute : ActionFilterAttribute
{
private const string CookieName = "XSRF-TOKEN";
private readonly IAntiforgery antiforgery;
public AngularAntiForgeryTokenAttribute(IAntiforgery antiforgery)
{
this.antiforgery = antiforgery;
}
public override void OnResultExecuting(ResultExecutingContext context)
{
base.OnResultExecuting(context);
if (!context.Cancel)
{
var tokens = antiforgery.GetAndStoreTokens(context.HttpContext);
context.HttpContext.Response.Cookies.Append(
CookieName,
tokens.RequestToken,
new CookieOptions { HttpOnly = false });
}
}
}
/* HomeController */
[ServiceFilter(typeof(AngularAntiForgeryTokenAttribute), IsReusable = true)]
public IActionResult Index()
{
return View();
}
/* AccountController */
[HttpPost()]
[AllowAnonymous]
[ValidateAntiForgeryToken]
// Send new antiforgery token
[ServiceFilter(typeof(AngularAntiForgeryTokenAttribute), IsReusable = true)]
public async Task<IActionResult> Register([FromBody] RegisterViewModel model)
{
//...
return Json(new { });
}
在Startup中注册属性,并配置Antiforgery服务读取请求令牌形式"X-XSRF-TOKEN" header.
public class Startup
{
// ...
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddScoped<AngularAntiForgeryTokenAttribute>();
services.AddAntiforgery(options =>
{
options.HeaderName = "X-XSRF-TOKEN";
});
}
}
不需要自定义操作过滤器。都可以在Startup.cs.
中连线
using Microsoft.AspNetCore.Antiforgery;
(...)
public void ConfigureServices(IServiceCollection services)
{
services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
(...)
}
public void Configure(IApplicationBuilder app, IAntiforgery antiforgery)
{
app.Use(next => context =>
{
if (context.Request.Path == "/")
{
//send the request token as a JavaScript-readable cookie, and Angular will use it by default
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions { HttpOnly = false });
}
return next(context);
});
(...)
}
然后,在您的控制器中,您需要的只是 [ValidateAntiForgeryToken] 装饰器,无论您想要强制提供令牌。
作为参考,我在这里找到了这个解决方案 - AspNet AntiForgery Github Issue 29。
我有一个 Angular2 应用程序。在ASP.NET5(Core).
内是运行
它对工作正常的控制器进行 Http 调用。
但现在我需要建立跨站脚本投影。
如何在每个 Http 请求上生成一个新令牌,然后在 Angular2 个应用中执行 AntiForgeryToken 检查?
注意:我在 Angular 中的数据表单不是从 MVC 视图生成的,而是完全用 Angular2 编写的,并且仅调用 Web 服务。
我看到的所有示例都已过时并且无法正常工作/无法完全正常工作。
我如何在 Angular2 中集成 AntiForgeryToken 检查以对抗 ASP.NET 5 其中表单是纯 Angular?
谢谢。
我认为您需要制作支持通过 header 而不是表单值发送令牌的自定义 AntiForgeryValidationToken 属性。然后将令牌添加到从 Angular2 应用程序到 api 的每个请求的 header。这里的例子 How do you set global custom headers in Angular2?
要验证来自 header 的令牌,您可以使用如下方法:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public sealed class ValidateHeaderAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException(nameof(filterContext));
}
var httpContext = filterContext.HttpContext;
if (httpContext.Request.Headers["__RequestVerificationToken"] == null)
{
httpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
httpContext.Response.StatusDescription = "RequestVerificationToken missing.";
filterContext.Result = new JsonResult
{
Data = new { ErrorMessage = httpContext.Response.StatusDescription },
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
return;
}
var cookie = httpContext.Request.Cookies[System.Web.Helpers.AntiForgeryConfig.CookieName];
System.Web.Helpers.AntiForgery.Validate(cookie != null ? cookie.Value : null, httpContext.Request.Headers["__RequestVerificationToken"]);
}
}
然后您只需在控制器中的方法上添加 [ValidateHeaderAntiForgeryToken]。但请注意,这是来自 MVC 5,ASP.NET 4.5.2 项目,因此您可能需要稍微更改它以适应 .NET Core。此外,我将其修改为 return 如果令牌丢失,结果为 JSON ,如果您不处理错误响应并将其输出给用户,则可以删除该部分。 此属性核心部分的学分转到:https://nozzlegear.com/blog/send-and-validate-an-asp-net-antiforgerytoken-as-a-request-header
困难的部分是如何在纯 Angular 2 应用程序(无法访问 .cshtml 文件)中不使用 @Html.AntiForgeryToken()
来生成 AntiForgeryToken。我也在寻找答案。
我正在使用操作过滤器发送请求令牌。 只需将其应用于您想要新防伪令牌的操作,例如Angular2 SPA、WebAPI 操作等
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class AngularAntiForgeryTokenAttribute : ActionFilterAttribute
{
private const string CookieName = "XSRF-TOKEN";
private readonly IAntiforgery antiforgery;
public AngularAntiForgeryTokenAttribute(IAntiforgery antiforgery)
{
this.antiforgery = antiforgery;
}
public override void OnResultExecuting(ResultExecutingContext context)
{
base.OnResultExecuting(context);
if (!context.Cancel)
{
var tokens = antiforgery.GetAndStoreTokens(context.HttpContext);
context.HttpContext.Response.Cookies.Append(
CookieName,
tokens.RequestToken,
new CookieOptions { HttpOnly = false });
}
}
}
/* HomeController */
[ServiceFilter(typeof(AngularAntiForgeryTokenAttribute), IsReusable = true)]
public IActionResult Index()
{
return View();
}
/* AccountController */
[HttpPost()]
[AllowAnonymous]
[ValidateAntiForgeryToken]
// Send new antiforgery token
[ServiceFilter(typeof(AngularAntiForgeryTokenAttribute), IsReusable = true)]
public async Task<IActionResult> Register([FromBody] RegisterViewModel model)
{
//...
return Json(new { });
}
在Startup中注册属性,并配置Antiforgery服务读取请求令牌形式"X-XSRF-TOKEN" header.
public class Startup
{
// ...
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddScoped<AngularAntiForgeryTokenAttribute>();
services.AddAntiforgery(options =>
{
options.HeaderName = "X-XSRF-TOKEN";
});
}
}
不需要自定义操作过滤器。都可以在Startup.cs.
中连线using Microsoft.AspNetCore.Antiforgery;
(...)
public void ConfigureServices(IServiceCollection services)
{
services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
(...)
}
public void Configure(IApplicationBuilder app, IAntiforgery antiforgery)
{
app.Use(next => context =>
{
if (context.Request.Path == "/")
{
//send the request token as a JavaScript-readable cookie, and Angular will use it by default
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions { HttpOnly = false });
}
return next(context);
});
(...)
}
然后,在您的控制器中,您需要的只是 [ValidateAntiForgeryToken] 装饰器,无论您想要强制提供令牌。
作为参考,我在这里找到了这个解决方案 - AspNet AntiForgery Github Issue 29。