You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用JWTService配置JwtBearer?规避不推荐的服务构建方式

问题:如何在AddJwtBearer中复用JWTService的TokenValidationParameters配置?

我正在应用中使用JwtBearer配置AuthenticationService,并将JWT配置抽象为JWTService以在全应用中复用,以下是我的代码:

builder.Services.AddSingleton<JWTService>();

builder.Services.AddAuthorization(options =>
{   
    options.AddPolicy("UserPolicy", p => p.RequireAuthenticatedUser().RequireClaim("Profession"));
});
builder.Services.AddAuthentication(x =>
{
    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
    options.TokenValidationParameters = ...;
});
public class JWTService
{
    private IConfiguration _configuration;

    public JWTService(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public TokenValidationParameters Config()
    {
        return new TokenValidationParameters()
        {
            ValidateActor = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ClockSkew = TimeSpan.Zero,
            ValidAudience = _configuration["JwtBearerTokenSettings:Audience"],
            ValidIssuer = _configuration["JwtBearerTokenSettings:Issuer"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JwtBearerTokenSettings:SecretKey"]))
        };
    }
}

请问如何获取JWTService并将其Config方法的返回值作为AddJwtBearer的参数?我曾通过builder.Services.BuildServiceProvider().GetServices实现,但该方式不被推荐,是否有其他可行方案?


解决方案

方案1:使用AddJwtBearer的服务提供者重载

AddJwtBearer提供了接受IServiceProvider的重载,可以在配置阶段从已注册的服务容器中获取JWTService,这是官方推荐的方式,避免提前构建服务容器导致的问题:

builder.Services.AddSingleton<JWTService>();

builder.Services.AddAuthorization(options =>
{   
    options.AddPolicy("UserPolicy", p => p.RequireAuthenticatedUser().RequireClaim("Profession"));
});

builder.Services.AddAuthentication(x =>
{
    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer((serviceProvider, options) =>
{
    // 从服务容器中获取已注册的JWTService实例
    var jwtService = serviceProvider.GetRequiredService<JWTService>();
    options.TokenValidationParameters = jwtService.Config();
});

这种方式不会创建额外的服务容器实例,避免了服务重复注册、状态不一致等问题,完全符合依赖注入的设计原则。

方案2:简化配置逻辑(无需依赖注入实例)

由于你的JWTService当前仅负责读取配置并返回TokenValidationParameters,没有其他业务逻辑或依赖,可以直接从IConfiguration构建参数,或者封装成静态工具类复用逻辑:

方式A:直接读取配置

var tokenValidationParams = new TokenValidationParameters()
{
    ValidateActor = true,
    ValidateAudience = true,
    ValidateLifetime = true,
    ValidateIssuerSigningKey = true,
    ClockSkew = TimeSpan.Zero,
    ValidAudience = builder.Configuration["JwtBearerTokenSettings:Audience"],
    ValidIssuer = builder.Configuration["JwtBearerTokenSettings:Issuer"],
    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["JwtBearerTokenSettings:SecretKey"]))
};

builder.Services.AddAuthorization(options =>
{   
    options.AddPolicy("UserPolicy", p => p.RequireAuthenticatedUser().RequireClaim("Profession"));
});

builder.Services.AddAuthentication(x =>
{
    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
    options.TokenValidationParameters = tokenValidationParams;
});

方式B:封装成静态工具类(复用逻辑)

public static class JwtConfigHelper
{
    public static TokenValidationParameters GetTokenValidationParameters(IConfiguration configuration)
    {
        return new TokenValidationParameters()
        {
            ValidateActor = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ClockSkew = TimeSpan.Zero,
            ValidAudience = configuration["JwtBearerTokenSettings:Audience"],
            ValidIssuer = configuration["JwtBearerTokenSettings:Issuer"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["JwtBearerTokenSettings:SecretKey"]))
        };
    }
}

然后在配置时调用:

var tokenValidationParams = JwtConfigHelper.GetTokenValidationParameters(builder.Configuration);

builder.Services.AddAuthorization(options =>
{   
    options.AddPolicy("UserPolicy", p => p.RequireAuthenticatedUser().RequireClaim("Profession"));
});

builder.Services.AddAuthentication(x =>
{
    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
    options.TokenValidationParameters = tokenValidationParams;
});

这种方式更轻量,不需要依赖注入容器,适合仅封装配置读取的场景。


内容的提问来源于stack exchange,提问作者Lucas Bustos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 18:15:07