【问题标题】:How to get IOptions in ConfigureServices method or pass IOptions into extension method?如何在 ConfigureServices 方法中获取 IOptions 或将 IOptions 传递给扩展方法?
【发布时间】:2019-02-14 22:14:27
【问题描述】:

我正在开发 asp .net core web api 2.1 应用程序。

我在静态类中添加了 JWT 认证服务作为扩展方法:

public static class AuthenticationMiddleware
{
    public static IServiceCollection AddJwtAuthentication(this IServiceCollection services, string issuer, string key)
    {
        services
            .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    // validate the server that created that token
                    ValidateIssuer = true,
                    // ensure that the recipient of the token is authorized to receive it
                    ValidateAudience = true,
                    // check that the token is not expired and that the signing key of the issuer is valid
                    ValidateLifetime = true,
                    // verify that the key used to sign the incoming token is part of a list of trusted keys
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = issuer,
                    ValidAudience = issuer,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key))
                };
            });

        return services;
    }
}

我在 Startup 类的 ConfigureServices 方法中使用如下:

public void ConfigureServices(IServiceCollection services)
{
    // adding some services omitted here

    services.AddJwtAuthentication(Configuration["Jwt:Issuer"], Configuration["Jwt:Key"]);

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

现在,我需要使用 IOptions 模式从 appsettings.json 获取 JWT 身份验证数据

如何在 ConfigureServices 方法中获取 IOptions 以将颁发者和密钥传递给扩展方法?或者如何将 IOptions 传递给扩展方法?

【问题讨论】:

标签: asp.net-web-api asp.net-core .net-core asp.net-core-2.0


【解决方案1】:

对于从appsettings.jsonModel 的绑定数据,您可以按照以下步骤操作:

  1. Appsettings.json 内容

    {
    "Logging": {
     "IncludeScopes": false,
     "LogLevel": {
        "Default": "Warning"
           }
     },      
     "JWT": {
          "Issuer": "I",
          "Key": "K"
        }
     }
    
  2. JWT 选项

    public class JwtOptions
    {
        public string Issuer { get; set; }
        public string Key { get; set; }
     }
    
  3. 启动.cs

    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<JwtOptions>(Configuration.GetSection("JWT"));
        var serviceProvider = services.BuildServiceProvider();
        var opt = serviceProvider.GetRequiredService<IOptions<JwtOptions>>().Value;
        services.AddJwtAuthentication(opt.Issuer, opt.Key);
        services.AddMvc();
    }
    
  4. 直接传递JwtOptions 的另一个选项。

    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<JwtOptions>(Configuration.GetSection("JWT"));
        var serviceProvider = services.BuildServiceProvider();
        var opt = serviceProvider.GetRequiredService<IOptions<JwtOptions>>().Value;
        services.AddJwtAuthentication(opt);
    
        services.AddMvc();
    }
    
  5. 更改扩展方法。

    public static IServiceCollection AddJwtAuthentication(this IServiceCollection services, JwtOptions opt)
    

【讨论】:

  • 关于选项 3 和 4:在 ConfigureServices 中使用 BuildServiceProvider() 似乎不是一个好主意。文档还说“不要在 Startup.ConfigureServices 中使用 IOptions 或 IOptionsMonitor。由于服务注册的顺序,可能存在不一致的选项状态。” docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/…
【解决方案2】:

另一种选择是将配置绑定到具有Bind() 扩展名的类。 (IMO 这是一个比 IOptions 更干净的解决方案)

public class JwtKeys
{
    public string Issuer { get; set; }
    public string Key { get; set; }
}

public void ConfigureServices(IServiceCollection services)
{
    var jwtKeys = new JwtKeys();
    Configuration.GetSection("JWT").Bind(JwtKeys);

    services.AddJwtAuthentication(jwtKeys);
}

public static IServiceCollection AddJwtAuthentication(this IServiceCollection services, JwtKeys jwtKeys)
{....}

然后,如果您需要在解决方案中的其他位置设置 JwtKeys,只需在集合上注册该类并在需要的地方注入它

services.AddSingleton(jwtKeys);

【讨论】:

  • Configuration.GetSection("JWT") 给我:error CS0120: An object reference is required for the non-static field, method, or property 'Configuration.GetSection(string)'
  • @IanGrainger 确保你已经初始化了 IConfiguration 属性配置
  • 是的,我没有。我真的想使用 IOptions,而不是指定文件并添加环境变量和所有这些 gubbins。
【解决方案3】:

您可以像这样在 Startup 类中将选项添加到 DI 容器:

public class JwtOptions
{
    public string Issuer { get; set; }
    public string Key { get; set; }

}

public void ConfigureService(IServiceCollection services)
{
    services.AddOptions();
    services.Configure<JwtOptions>(Configuration.GetSection("Jwt"));
}

现在您可以在配置阶段或扩展方法中使用此选项:

public void Configure(IApplicationBuilder app)
{
    var options = app.ApplicationServices.GetService<IOptions<JwtOptions>();
    // write your own code
}

【讨论】:

  • 不幸的是,这似乎没有回答这个问题。 OP 希望访问 IOptions 内部的 ConfigureServices 而不是 Configure
  • 尽管它不适用于 OP,但它适用于我。谢谢!
猜你喜欢
  • 1970-01-01
  • 2020-01-23
  • 2018-07-30
  • 2015-10-30
  • 2020-08-30
  • 2019-01-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多