【问题标题】:AntiForgery Token using ASP.NET5 Web API without System.Web.Helpers on NET46AntiForgery 令牌在 NET46 上使用 ASP.NET5 Web API 而没有 System.Web.Helpers
【发布时间】:2015-06-23 04:15:08
【问题描述】:

尝试在 ASP.NET5 (aka vNext) API 上实现 AntiForgery

我找到的所有文章都来自this article,并使用了System.Web.Helpers.AntiForgery.GetTokens,这不应该是ASP.NET5的方式

private static string GetTokenHeaderValue() 
{
   string cookieToken, formToken;
   System.Web.Helpers.AntiForgery.GetTokens(null, out cookieToken, out formToken);
   return cookieToken + ":" + formToken;
}

是否有任何实现实际上展示了如何在 ASP.NET5 中检索这些令牌

其他来源ASP.NET5 AntiForgery Source Code

【问题讨论】:

    标签: asp.net asp.net-mvc asp.net-web-api owin antiforgerytoken


    【解决方案1】:

    现在有一个sample in the source code。该示例使用 Angular 1.x。在该示例的基础上,通过使用过滤器进行验证,这是一个粗略的示例。 Startup 需要设置令牌:

    public void Configure(IApplicationBuilder app, IAntiforgery antiforgery)
    {
        app.Use(next => context =>
        {
            if (!context.Request.Path.Value.StartsWith("/api/"))
            {
                // We can 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);
        });
        …
    }
    

    然后可以使用过滤器来验证令牌:

    public class AntiforgeryValidationFilter : IAsyncActionFilter
    {
        private readonly IAntiforgery antiforgery;
    
        public AntiforgeryValidationFilter(IAntiforgery antiforgery)
        {
            this.antiforgery = antiforgery;
        }
    
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            if (context.HttpContext.Request.Path.Value.StartsWith("/api/"))
            {
                await antiforgery.ValidateRequestAsync(context.HttpContext);
            }
            await next();
        }
    }
    

    然后在Startup注册过滤器:

    public void ConfigureServices(IServiceCollection services)
    {
        // Angular's default header name for sending the XSRF token.
        services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
    
        services
            .AddMvc(options =>
                options.Filters.Add(typeof(AntiforgeryValidationFilter)))
            …
    }
    

    【讨论】:

    • 我正在尝试实现您的选项,但它在第一个 app.Use 语句中失败,它返回以下错误:无法将 lambda 表达式转换为预期的委托类型,因为某些块中的返回类型不能隐式转换为委托返回类型。那里有什么问题?
    • @RobertJ。你包括return next(context); 吗?您是否尝试过运行提到的示例?它还使用app.Use,所以它可能是可以工作的。
    • 我复制粘贴了您的提案(稍作调整),它给了我提到的错误。会不会是我使用的是 ASP.NET CORE RC2 版本,他们改变了什么?
    • 如果是这样的话,我会感到惊讶,但也许。我会尝试运行their sample。
    【解决方案2】:

    使用 MVC 实现此功能的另一种方法是使用 HTML 帮助器获取视图上的令牌,该令牌创建 cookie 和隐藏的输入字段令牌。

    <form>
    @Html.AntiForgeryToken()
    </form>
    

    HTML 输出:

    <input name="__RequestVerificationToken" type="hidden" value="*** />
    

    现在表单标记已经存在,我们可以在标头中发送标记或将其添加到 API 期望的模型中。可以使用处理自定义 Antiforgery 令牌验证的 ActionFilter 来保护 API。 [Authorize] 的工作原理类似

    [ValidateAntiForgeryToken]
    public class MyController : ApiController
    

    逻辑是读取可以在其中找到 cookie 和标头值标记的标头。然后可以使用对

    的调用进行评估
    AntiForgery.Validate(cookieToken, headerToken);
    

    然后过滤器可以接受或拒绝请求。

    通过返回拒绝:

    HttpStatusCode.Forbidden

    【讨论】:

      【解决方案3】:

      在控制器生成

      using Microsoft.AspNet.Mvc;
      using Microsoft.Framework.DependencyInjection;
      
      namespace MyApp.App.Controllers
      {
          public class MyController : Controller
          {
              public string GetAntiForgeryTokens()
              {
                  var antiForgery = Context.RequestServices.GetService<AntiForgery>();
                  AntiForgeryTokenSet antiForgeryTokenSet = antiForgery.GetTokens(Context, null);
                  string output = antiForgeryTokenSet.CookieToken + ":" + antiForgeryTokenSet.FormToken;
                  return output;
              }
          }    
      }
      

      在视图中生成

      @inject AntiForgery antiForgery
      @functions
      {
          public string GetAntiForgeryTokens()
          {
              AntiForgeryTokenSet antiForgeryTokenSet = antiForgery.GetTokens(Context, null);
              string output = antiForgeryTokenSet.CookieToken + ":" + antiForgeryTokenSet.FormToken;
              return output;
          }
      }
      
      <body>
          @GetAntiXsrfToken()
      </body>
      

      验证

      var antiForgery = Context.RequestServices.GetService<AntiForgery>();
      antiForgery.Validate(Context, new AntiForgeryTokenSet(formToken, cookieToken));
      

      【讨论】:

      • 我相信你应该重新检查你的代码。或者确保自 2015 年 4 月 18 日以来没有任何重大变化。当我编写该代码时,那里有一个上下文,其他 3 个人也将此答案标记为对他们有用...
      • 我正在尝试在 Core1 框架中执行此操作。我认为这是 aspnet 4.6
      • 好的,但问题标题是 ASP NET 5
      • 我希望我知道微软当时的计划。据我记得当时没有Core1(否则我会说出来)。我现在将框架名称添加到标题中
      猜你喜欢
      • 2017-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-15
      相关资源
      最近更新 更多