【问题标题】:Using ASP.NET Core 6 Web API Antiforgery Token in extern consumer (App) without Authentication在没有身份验证的外部消费者(应用程序)中使用 ASP.NET Core 6 Web API Antiforgery Token
【发布时间】:2022-01-02 20:32:53
【问题描述】:

如何将 ASP.NET Core 6 Web API 中的防伪令牌与 iOS 或 Android 应用程序等外部消费者一起使用?我不需要对请求进行用户身份验证。该应用托管在另一个域中。

我开发了一个带有防伪令牌 (Followed this link) 和 ASP.NET 6 Razor 页面的 Web API。一切正常。但是我怎样才能开发一个使用这个 Web API 的外部应用程序呢?问题,我不知道如何从“外部”应用程序创建防伪令牌?如何配置应用程序以使用带有防伪令牌的 Web API?

【问题讨论】:

    标签: c# asp.net asp.net-core asp.net-core-webapi antiforgerytoken


    【解决方案1】:

    我不同意“在构建 API 时没有必要针对 CSRF 攻击实施 Anti-Forgery Token 保护”的答案。

    仍然存在入侵者以某种方式强制客户端应用发送恶意请求的风险。


    要在 .NET Web API 中配置防伪保护(不使用 MVC 视图),您需要使用包 Microsoft.AspNetCore.Antiforgery

    请记住,有两个正在验证的令牌:Cookie 令牌和请求令牌(来自 HTTP 标头)。

    // Field
    IAntiforgery _antiforgery;
    
    var tokens = _antiforgery.GetAndStoreTokens(HttpContext);
    

    因此,tokens 将包含以下值:

    {
        "CookieToken": "CfDJ8JPuS3COPd9AmHCMBz_IFVdVzR8cfeD2or9v3qMLlWgRiN812hKbkh4o8TpYl4AdA3uJ3FeoY3eozx59q_uSnloXl80nLEd6twLzkDdn4AifcsGWcwaAxWSrGTui0vwl7-SHjftCfkbj9pAlDC_DS0Q",
        // Ignore this: built-in mechanism for forms
        "FormFieldName": "__RequestVerificationToken",
        "HeaderName": "X-XSRF-TOKEN",
        "RequestToken": "CfDJ8JPuS3COPd9AmHCMBz_IFVfnP50wBywG2WJmFoYA7nx-VGzBjPRY16-p3BBFRMUGHt4cz-M-VrZ_jX_7vUoIt0OX3xhHNw8swt0CebGa4P41cVej2F_DvvayOvrhbY6s3Z2U1aZWHmAvBT8NlH7ueRE"
    }
    

    注意CookieTokenRequestToken 是不同的。

    Cookie 令牌是自动处理的。但是Request Token应该由我们来处理。

    1. 创建一个验证中间件:

      public class AntiforgeryMiddleware : IMiddleware
      {
          private readonly IAntiforgery _antiforgery;
      
          public AntiforgeryMiddleware(IAntiforgery antiforgery)
          {
              _antiforgery = antiforgery;
          }
      
          public async Task InvokeAsync(HttpContext context, RequestDelegate next)
          {
              var isGetRequest = string.Equals("GET", context.Request.Method, StringComparison.OrdinalIgnoreCase);
              if (!isGetRequest)
              {
                  _antiforgery.ValidateRequestAsync(context).GetAwaiter().GetResult();
              }
      
              await next(context);
          }
      }
      
    2. 在您的 Web API 应用程序中配置 DI:

      // Startup.cs
      public void ConfigureServices(IServiceCollection services)
      {
          // ...
      
          // Extension method comes from the `Microsoft.AspNetCore.Antiforgery` package
          services.AddAntiforgery(options =>
          {
              options.HeaderName = "X-XSRF-TOKEN";
          });
      
          services.AddScoped<AntiforgeryMiddleware>();
      }
      
    3. 配置验证中间件:

      // Startup.cs
      public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
      {
          // ...
      
          app.UseMiddleware<AntiforgeryMiddleware>();
      
          app.UseEndpoints(endpoints =>
          {
              endpoints.MapControllers();
          });
      }
      
    4. 创建一个 XSRF Token 端点:

      [Route("api/xsrf-token")]
      [ApiController]
      public class AntiForgeryController : Controller
      {
          private IAntiforgery _antiforgery;
      
          public AntiForgeryController(IAntiforgery antiforgery)
          {
              _antiforgery = antiforgery;
          }
      
          [IgnoreAntiforgeryToken]
          public IActionResult Get()
          {
              // Creates and sets the cookie token in a cookie
              // Cookie name will be like ".AspNetCore.Antiforgery.pG4SaGh5yDI"
              var tokens = _antiforgery.GetAndStoreTokens(HttpContext);
      
              // Take request token (which is different from a cookie token)
              var headerToken = tokens.RequestToken;
              // Set another cookie for a request token
              Response.Cookies.Append("XSRF-TOKEN", headerToken, new CookieOptions
              {
                  HttpOnly = false
              });
              return NoContent();
          }
      }
      
    5. 在客户端向 URL /api/xsrf-token 发出请求。

      然后读取请求令牌 cookie XSRF-TOKEN 并将其设置为非 GET 请求的 X-XSRF-TOKEN HTTP 标头:

      X-XSRF-TOKEN: <request-token>
      

    【讨论】:

    • 但是每个人都可以提出请求/api/xsrf-token 来获取令牌?这里的安全性如何?
    【解决方案2】:

    在构建 API 时没有必要针对 CSRF 攻击实施 Anti-Forgery Token 保护,因为 API 的构建和使用方式需要不同的保护方法,例如:

    • 使用 API 密钥。
    • 使用基本身份验证。
    • 使用 OpenID Connect。

    因为目标是防止恶意客户端调用我们的 API,所以我们需要验证执行 API 请求的客户端应用的身份。

    并且为了执行 CSRF 攻击,主要条件之一是拥有基于 Cookie 的身份验证会话(查看此article,其中详细解释了如何执行 CSRF 攻击),这不是API 的情况。

    但是,如果您使用 Ajax 从您的网站调用您的 API,并且该 API 与该网站位于同一来源,并且您依赖 Cookie 来验证用户身份,则可以(并且您应该)集成 Anti- Forgery Token protection,你可以查看这个Answer on StackOverflow了解如何实现它的更多细节。

    但由于您要从外部应用程序调用 API,只需使用上述方法之一即可。

    查看Microsoft docs 上的这篇文章,了解有关 CSRF 攻击以及如何实施防伪令牌保护的更多详细信息。

    另外,请查看 RedHat 的这篇文章以获取有关 API security 的更多信息。

    【讨论】:

      猜你喜欢
      • 2018-06-16
      • 2021-05-30
      • 2018-06-15
      • 1970-01-01
      • 2019-01-14
      • 2017-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多