配置认证与授权

1
2
3
4
5
// 添加认证服务
builder.Services.AddAuthentication();

// 添加授权服务
builder.Services.AddAuthorization();

AddAuthentication():注册认证系统,用JWT认证。
AddAuthorization():注册授权系统,用于在 [Authorize] 等特性中判断用户是否有权限访问。

读取并绑定 JWT 配置,注册 JWT 认证方案

1
2
// 从配置中获取 JWT 相关配置
JWTOptions jwtOpt = configuration.GetSection("JWT").Get<JWTOptions>();

从配置源读取JWT节点,并绑定到 JWTOptions 对象里。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class JWTOptions
{
/// <summary>
/// 令牌颁发者(Issuer)。
/// </summary>
public string Issuer { get; set; }

/// <summary>
/// 令牌接收者(Audience)。
/// </summary>
public string Audience { get; set; }

/// <summary>
/// 用于签名 JWT 的密钥。
/// </summary>
public string Key { get; set; }

/// <summary>
/// 令牌过期时间(秒)。
/// </summary>
public int ExpireSeconds { get; set; }
}
1
2
// 配置 JWT 选项绑定
services.Configure<JWTOptions>(configuration.GetSection("JWT"));

services
依赖注入容器(IServiceCollection)实例。这里我们往容器中添加配置绑定。
Configure<TOptions>
来自 Microsoft.Extensions.Options.ConfigurationExtensions,用于把配置文件里的某个部分绑定到 TOptions 类型,并注册成 Options 模式 对象。
注册后,你可以在任何地方通过 IOptions<JWTOptions>来获取这个对象。

1
2
// 添加 JWT 认证服务
builder.Services.AddJWTAuthentication(jwtOpt);

注册JWT服务需要配置JWT令牌验证参数,这里自定义了AddJWTAuthentication扩张方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public static class AuthenticationExtensions
{
/// <summary>
/// 向服务集合中添加JWT认证。
/// </summary>
/// <param name="services">服务集合。</param>
/// <param name="jwtOpt">JWT配置选项。</param>
/// <returns>认证生成器。</returns>
public static AuthenticationBuilder AddJWTAuthentication(this IServiceCollection services, JWTOptions jwtOpt)
{
return services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(x =>
{
// 配置JWT令牌验证参数
x.TokenValidationParameters = new()
{
ValidateIssuer = true, // 验证签发者
ValidateAudience = true, // 验证接收者
ValidateLifetime = true, // 验证有效期
ValidateIssuerSigningKey = true, // 验证签名密钥
ValidIssuer = jwtOpt.Issuer, // 有效签发者
ValidAudience = jwtOpt.Audience, // 有效接收者
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOpt.Key)), // 签名密钥
};
});
}
}

AuthenticationBuilder —— 方便你后面继续链式配置认证

AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
告诉 ASP.NET Core 默认使用 Bearer Token(即 Authorization: Bearer <token>)来认证。
AddJwtBearer(…)
注册 JWT Bearer 认证处理器,并配置如何验证 token。
TokenValidationParameters
ValidateIssuer / ValidIssuer:检查 token 里 iss 声明是否和配置一致。
ValidateAudience / ValidAudience:检查 token 里 aud 声明是否和配置一致。
ValidateLifetime:检查 token 是否过期(取决于 exp 和 nbf 字段)。
ValidateIssuerSigningKey:检查 token 签名是否有效(防篡改)。
IssuerSigningKey:签名用的密钥(这里用 HMACSHA256 对称加密)。

配置 Swagger 支持 JWT 调试

1
2
3
4
builder.Services.Configure<SwaggerGenOptions>(c =>
{
c.AddAuthenticationHeader();
});

给 Swagger UI 添加一个 “Authorize” 按钮,可以输入 Bearer Token,在接口调试时自动带上 Authorization 头。
AddAuthenticationHeader是自定义扩张方法,向 Swagger 配置中添加认证头(Authorization Header), 使得在 Swagger UI 中可以输入 JWT Token 进行接口测试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public static class SwaggerGenOptionsExtensions
{
/// <summary>
/// 向 Swagger 配置中添加认证头(Authorization Header),
/// 使得在 Swagger UI 中可以输入 JWT Token 进行接口测试。
/// </summary>
/// <param name="c">SwaggerGenOptions 实例。</param>
public static void AddAuthenticationHeader(this SwaggerGenOptions c)
{
// 添加安全定义,指定名称为 "Authorization",类型为 ApiKey,位置在 Header。
// 这样在 Swagger UI 中会出现一个输入框用于填写 Token。
c.AddSecurityDefinition("Authorization", new OpenApiSecurityScheme
{
// 描述信息,指导用户如何填写 Token。
Description = "Authorization header .\r\n Example:'Bearer 12345abcdef'",
// 指定参数在 HTTP Header 中传递。
In = ParameterLocation.Header,
// 安全方案类型为 ApiKey。
Type = SecuritySchemeType.ApiKey,
// 方案名称,通常为 "Authorization"。
Scheme = "Authorization"
});

// 添加安全需求,指定所有接口都需要携带 "Authorization" 头部。
c.AddSecurityRequirement(new OpenApiSecurityRequirement()
{
{
new OpenApiSecurityScheme
{
// 引用上面定义的安全方案。
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id="Authorization"
},
// 方案类型为 oauth2(虽然实际类型为 ApiKey,这里用于兼容性)。
Scheme = "oauth2",
// 头部名称。
Name="Authorization",
// 参数位置为 Header。
In=ParameterLocation.Header,
},
// 作用域列表,这里为空表示不限定作用域。
new List<string>()
}
});
}
}

在 Swagger UI 顶部加一个 “Authorize” 按钮。
让所有 API 请求都自动带上 Authorization HTTP 头。