【问题标题】:How to implement versioning for Token endpoint in Web API 2如何在 Web API 2 中实现 Token 端点的版本控制
【发布时间】:2020-05-27 23:13:18
【问题描述】:

我有一个使用基于令牌的身份验证 (OAuth2) 的 Asp.Net Web API 2。

我已经使用 aspnet-api-versioning 实现了 Web API 版本控制。

所以现在我拥有三个不同版本的 API。真的很棒,我现在可以在不影响当前 API 的情况下更改 V3。

但是/token 端点没有版本控制,因为它不在我的控制器中。它在 Providers 中。

我搜索了但找不到任何有用的东西。

【问题讨论】:

    标签: asp.net-web-api oauth-2.0 asp.net-identity bearer-token api-versioning


    【解决方案1】:

    我们可以在 Startup.Auth.cs 中注册多个令牌端点

    这就是我所做的:

            OAuthOptions = new OAuthAuthorizationServerOptions
            {
                TokenEndpointPath = new PathString("/Token"),
                Provider = new ApplicationOAuthProvider(PublicClientId),
                AuthorizeEndpointPath = new PathString("/Account/ExternalLogin"),
                AccessTokenExpireTimeSpan = TimeSpan.FromDays(TokenExpirationInDays),
                AllowInsecureHttp = true, //Allow HTTP to send username password.
            };
            app.UseOAuthBearerTokens(OAuthOptions);
    
            OAuthOptionsV3 = new OAuthAuthorizationServerOptions
            {
                TokenEndpointPath = new PathString("/api/V3/Accounts/Token"),
                Provider = new ApplicationOAuthProvider2(PublicClientId),
                AccessTokenExpireTimeSpan = TimeSpan.FromDays(TokenExpirationInDays),
                AllowInsecureHttp = true, //Allow HTTP to send username password.
            };
            // Enable the application to use bearer tokens to authenticate users
            app.UseOAuthBearerTokens(OAuthOptionsV3);
    

    所以现在每个版本都有不同的令牌端点。

    【讨论】:

      【解决方案2】:

      我不熟悉这个特定的设置,但这看起来像中间件。这里没有足够的信息来为您提供具体的答案,但您的目标应该可以通过以下几种方式之一实现:

      选项 1 - 使用约定 API

      如果您的授权端点实际上是一个控制器(尽管我认为它不是),您可以像这样使用 Conventions API

      services.AddApiVersioning(options =>
      {
          options.Conventions.Controller<OAuthController>().IsApiVersionNeutral();
      }
      

      约定专门用于处理控制器可能在外部定义且您无法控制源代码的情况。

      选项 2 - 使用自定义约定

      中间件可以动态创建动作。只要实际产生了动作,就可以使用自定义的IControllerConvention。您将获得 ControllerModel,其中包含您需要版本化的操作。假设这是正确的行为,您将在源模型中寻找匹配的操作,然后您可以将其应用于控制器约定,例如:

      public class MyConventions : IControllerConvention
      {
        public bool Apply(IControllerConventionBuilder controller, ControllerModel controllerModel)
        {
          var method = // TODO: resolve the target method from controllerModel
      
          if (method == null)
          {
            return false;
          }
      
          controller.Action(method).IsApiVersionNeutral();
          return false;
        }
      }
      

      选项 3 - 在中间件中

      如果这是纯中间件,则不直接支持 API 版本控制。但是,如果管道组合正确,您可以自己支持版本控制。具体来说,API 版本控制必须先于需要它的中间件的其他部分。这通常会自动发生,但如果您需要控制注册,则需要更改设置以手动处理,如下所示:

      services.AddApiVersioning(options => options.RegisterMiddleware = false);
      
      // ... inside application setup
      services.UseApiVersioning();
      

      API 版本控制中间件并没有真正做任何特别的事情。它只是增加了一个管道功能。只要那是在您的其他中间件之前,它就会像这样在下游可用:

      var feature = context.Features.Get<IApiVersioningFeature>();
      
      // the raw, unparsed API version, if any
      var rawApiVersion = feature.RawApiVersion;
      
      // the parse API version; will be null if no version is specified
      // or the value cannot be parsed
      var apiVersion = feature.ApiVersion;
      
      // TODO: enforce versioning policies within the middleware
      

      选项 4 - 使用 API Explorer

      如果之前的方法都不适合您,您可以利用 API 资源管理器扩展 API 版本控制从发现的 API 构建您的配置(如上所述)。这将具有无需硬编码或每次发布新版本时都需要更改的优点。

      您的应用程序启动配置将更改为以下内容:

      public void Configure(IApplicationBuilder app, IApiVersionDescriptionProvider provider)
      {
        foreach (var description in provider.ApiVersionDescriptions)
        {
          var options = new OAuthAuthorizationServerOptions()
          {
            TokenEndpointPath = new PathString($"/api/{description.GroupName}/Accounts/Token"),
            Provider = new ApplicationOAuthProvider2(PublicClientId),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(TokenExpirationInDays),
            AllowInsecureHttp = true,
          };
      
          app.UseOAuthBearerTokens(options);
        }
      }
      

      【讨论】:

      • 前三个选项是不合适的版本控制方法,因为我的端点不是控制器方法。最后一个选项适用于令牌端点,但我希望每个版本都有不同的实现。
      • 选项 4 将与您提到的(我假设的)对您有用,但作为所有 API 版本的循环。如果每个 API 版本都有特定的自定义或其他策略,则可能需要与定义的 API 版本相交的映射。例如,您可能有一个工厂,它返回特定 API 版本的 OAuthAuthorizationServerOptions。然后你只需要如图所示调用app.UseOAuthBearerTokens(options)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-29
      • 2021-08-24
      • 1970-01-01
      相关资源
      最近更新 更多