【问题标题】:Angular2 ASP.NET Core AntiForgeryTokenAngular2 ASP.NET Core AntiForgeryToken
【发布时间】:2016-07-17 15:36:00
【问题描述】:

我有一个 Angular2 应用。它在 ASP.NET 5 (Core) 中运行。
它对工作正常的控制器进行 Http 调用。

但现在我需要建立跨站脚本投影。

如何在每个 Http 请求上生成一个新令牌,然后在 Angular2 应用程序中执行 AntiForgeryToken 检查?

注意:我在 Angular 中的数据表单不是从 MVC 视图生成的,而是完全用 Angular2 编写的,并且只调用 Web 服务。

我看到的所有例子都过时了,不能工作/不能完全工作。

如何在 Angular2 中针对表单是纯 Angular 的 ASP.NET 5 集成 AntiForgeryToken 检查?

谢谢。

【问题讨论】:

    标签: web-services angular asp.net-core xss


    【解决方案1】:

    我认为您需要制作自定义 AntiForgeryValidationToken 属性,该属性支持通过标头而不是表单值发送令牌。然后将令牌添加到从您的 Angular2 应用程序到您的 api 的每个请求的标头中。这里的例子How do you set global custom headers in Angular2?

    【讨论】:

      【解决方案2】:

      要从标头验证令牌,您可以使用以下内容:

      [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。如果令牌丢失,我还修改了它以返回 JSON 结果,如果您不处理错误响应并将其输出给用户,则可以删除该部分。 此属性的核心部分归功于:https://nozzlegear.com/blog/send-and-validate-an-asp-net-antiforgerytoken-as-a-request-header

      困难的部分是如何在纯 Angular 2 应用程序中不使用 @Html.AntiForgeryToken() 生成 AntiForgeryToken(无法访问 .cshtml 文件)。我也在寻找答案。

      【讨论】:

      • 我想知道您是否找到了如何在不使用 @Html.AntiForgeryToken() 的情况下创建令牌的答案?
      【解决方案3】:

      我正在使用操作过滤器来发送请求令牌。 只需将其应用于您想要新的防伪令牌的操作,例如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”头。

      public class Startup
      {
          // ...
      
          public void ConfigureServices(IServiceCollection services)
          {
              // ...
      
              services.AddScoped<AngularAntiForgeryTokenAttribute>();
              services.AddAntiforgery(options =>
              {
                  options.HeaderName = "X-XSRF-TOKEN";
              });
          }
      }
      

      【讨论】:

      • 关于如何在 SPA 中使用这种方法的任何建议? GET 操作几乎不会被命中(/Home/Index 除外),您如何为稍后将发布 POST 的每个表单提供一个新令牌?
      • 尝试将 AngularAntiForgeryTokenAttribute 应用于您的 POST 端点。您应该能够在 POST 操作中更新令牌。
      【解决方案4】:

      不需要自定义操作过滤器。都可以在 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

      【讨论】:

      • 我按照上述步骤操作,但收到 400 错误请求错误。我的“发布”请求作为“选项:方法类型”发送到服务器。我就这个问题提出了一个问题-stackoverflow.com/questions/44841588/…
      • 我今天发现的一些附加信息 - 如果您在 IIS 中托管,您应该在服务器上配置数据保护,以便保留用于生成 AntiForgeryToken 的密钥。否则,应用程序重新启动时令牌将失效。有关如何配置的信息,请参见此处 - docs.microsoft.com/en-us/aspnet/core/publishing/…
      猜你喜欢
      • 1970-01-01
      • 2018-06-11
      • 2013-01-03
      • 2017-03-07
      • 1970-01-01
      • 2017-11-21
      • 2010-11-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多