C#开发日记:使用生成的JWT设置资源接口验证

目录

一、注册身份验证服务

二、配置JwtBearer身份验证

2.1 注册JwtBearer认证——AddJwtBearer方法

2.2 Jwt验证选项参数汇总——JwtBearerOptions

三、测试

3.1配置授权

3.2 使用token访问授权接口


继上次“C#开发日记:手把手教你生成JWT” 后:http://t.csdnimg.cn/78CkH

我们这次使用生成的Token为其他接口设置验证,上次使用的命名空间是:Microsoft.IdentityModel.Tokens;

这次需要再安装:Microsoft.AspNetCore.Authentication.JwtBearer

一、注册身份验证服务

在 Microsoft.Extensions.DependencyInjection.IServiceCollection 中注册注册身份验证服务的方法为AddAuthentication,是IServiceCollection的扩展方法。

public static AuthenticationBuilder AddAuthentication(this IServiceCollection services);
public static AuthenticationBuilder AddAuthentication(this IServiceCollection services, string defaultScheme);

public static AuthenticationBuilder AddAuthentication(this IServiceCollection services, Action<AuthenticationOptions> configureOptions);

选择第三个带有action<T>委托的身份验证选项

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(options = >{ 

//身份验证选项 AuthenticationOptions
    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
    //options.DefaultAuthenticateScheme=...;
    //options.DefaultSignInScheme=...;
    //options.DefaultSignOutScheme=...;
    //options.DefaultChallengeScheme=...;
    //options.DefaultForbidScheme=...,
    //options.RequireAuthenticatedSignIn=...;

})

二、配置JwtBearer身份验证

2.1 注册JwtBearer认证——AddJwtBearer方法

如果使用默认方案Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme

来启用 JwtBearer认证通过调用 重载2 AddJwtBearer("Bearer", delegate{});来指定默认。

AddJwtBearer的部分定义如下:

public static class JwtBearerExtensions
{
    // 默认方案
    public static AuthenticationBuilder AddJwtBearer(this AuthenticationBuilder builder)
    {
       //使用如下方法重载
        return builder.AddJwtBearer("Bearer", delegate
        {
        });
    }
... 省略其他

        //重载1

        public static AuthenticationBuilder AddJwtBearer(this AuthenticationBuilder builder, string authenticationScheme, Action<JwtBearerOptions> configureOptions)
    {
        return builder.AddJwtBearer(authenticationScheme, null, configureOptions);
    }
    // 重载2

    public static AuthenticationBuilder AddJwtBearer(this AuthenticationBuilder builder, string authenticationScheme, string? displayName, Action<JwtBearerOptions> configureOptions)
    {
        builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<JwtBearerOptions>, JwtBearerConfigureOptions>());
        builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<JwtBearerOptions>, JwtBearerPostConfigureOptions>());
        return builder.AddScheme<JwtBearerOptions, JwtBearerHandler>(authenticationScheme, displayName, configureOptions);
    }


}

可以看出默认AddJwtBearer会调用其重载1方法,输入字符串参数和又一个JwtBearerOptions类型的Action<T>委托,然后返回一个重载2:

AddJwtBearer(authenticationScheme, null, configureOptions);

参数分别是:

  • 身份验证方案名称(string): authenticationScheme
  • 身份验证处理程序的显示名称(可选): null
  • 允许配置 Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerOptions 委托: configureOptions

返回验证构造器的引用—— AddScheme,它是第一章节中"注册身份验证服务"用到的AuthenticationBuilder类自身的 AddScheme方法,它用于添加一项特定类型的身份验证机制。

builder.AddScheme<JwtBearerOptions, JwtBearerHandler>(authenticationScheme, null, configureOptions);

已知就只剩JwtBearerOptions类型的action<T>委托configureOptions还未设置值,利用AddJwtBearer返回的引用(AddScheme),在第一章 注册身份验证服务的基础上来配置JwtBearerOptions选项类。

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using System.Text;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(options => { options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; })
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidIssuer = "dlht",
            ValidateAudience = false,
            ValidateIssuerSigningKey = true,
            IssuerSigningKey =
                new SymmetricSecurityKey(
                    Encoding.UTF8.GetBytes(builder.Configuration.GetSection("JWT_SECRET_KEY").Value!)),
            ValidateLifetime = true,
            RequireExpirationTime = true,
            ClockSkew = TimeSpan.FromSeconds(30)
        };

        options.SaveToken = true;
        options.Events = new JwtBearerEvents
        {
            OnMessageReceived = context =>
            {
                var accessToken = context.Request.Query["access_token"];

                if (!string.IsNullOrEmpty(accessToken))
                {
                    context.Token = accessToken;
                }

                return Task.CompletedTask;
            },
            OnAuthenticationFailed = context =>
            {
                var e = context.Exception;
                return Task.CompletedTask;
            }
        };
    });

2.2 Jwt验证选项参数汇总——JwtBearerOptions

为了记忆理解上述行为配置的含义,我总结了JwtBearerOptions选项类的属性和其行为:

属性名类型默认值摘要/行为描述
RequireHttpsMetadatabooltrue是否需要HTTPS进行元数据地址或权限的访问,默认为true。
MetadataAddressstring无默认值获取元数据的发现端点。
Authoritystring?null进行OpenIdConnect调用时使用的权限。
Audiencestring?null接收到的OpenIdConnect令牌的单个有效受众值。
Challengestring"Bearer"放在"WWW-Authenticate"头中的挑战。
EventsJwtBearerEvents无默认值由应用程序提供的处理由承载认证处理器引发的事件的对象。
BackchannelHttpHandlerHttpMessageHandler?null用于检索元数据的HttpMessageHandler。
BackchannelHttpClient无默认值用于检索元数据的后端通道。
BackchannelTimeoutTimeSpan1分钟使用后端通道进行HTTP调用时的超时时间。
ConfigurationOpenIdConnectConfiguration?null直接由开发者提供的配置。如果提供,则不会使用MetadataAddress和后端通道属性。
ConfigurationManagerIConfigurationManager<OpenIdConnectConfiguration>?null负责从元数据中检索、缓存和刷新配置。如果没有提供,则会使用MetadataAddress和后端通道属性创建一个。
RefreshOnIssuerKeyNotFoundbooltrue在SecurityTokenSignatureKeyNotFoundException之后是否尝试刷新元数据。
SecurityTokenValidatorsIList<ISecurityTokenValidator>一个包含_defaultHandler的列表用于验证访问令牌的ISecurityTokenValidator列表。已过时,建议使用TokenHandlers。
TokenHandlersIList<TokenHandler>一个包含_defaultTokenHandler的列表用于验证访问令牌的TokenHandler列表。
TokenValidationParametersTokenValidationParameters新实例用于验证身份令牌的参数。
SaveTokenbooltrue定义在成功授权后,是否应该在AuthenticationProperties中存储承载令牌。
IncludeErrorDetailsbooltrue定义是否应该将令牌验证错误返回给调用者。默认启用。
MapInboundClaimsbooltrue定义是否应该将提取的JSON声明的名称映射为声明类型。
AutomaticRefreshIntervalTimeSpan默认自动刷新间隔自动刷新元数据的频率。
RefreshIntervalTimeSpan默认刷新间隔在检索失败或显式请求刷新的情况下,两次检索之间的最小时间。
UseSecurityTokenValidatorsboolfalse定义是使用TokenHandlers还是SecurityTokenValidators来验证传入的令牌。

okenValidationParameters 类在 ASP.NET Core 身份验证框架中用于定义验证 JWT(JSON Web Tokens)时所需的参数。

属性名类型默认行为/摘要描述
AlgorithmValidatorFunc<string, bool>验证签名算法的委托,用于确定是否接受令牌使用的特定签名算法。
ActorValidationParametersTokenValidationParameters用于验证令牌中的 Actor 声明的参数。
AudienceValidatorFunc<IEnumerable<string>, bool>验证受众(Audience)声明的委托。
ClockSkewTimeSpan允许的时钟偏差,用于调整令牌的过期时间,以处理时钟不同步的情况。
ConfigurationManagerIConfigurationManager<OpenIdConnectConfiguration>用于配置管理的接口,例如用于OpenID Connect配置。
CryptoProviderFactoryICryptoProviderFactory用于创建加密提供者的工厂。
IssuerSigningKeySecurityKey用于验证令牌签名的密钥。
IssuerSigningKeysIEnumerable<SecurityKey>用于验证签名的密钥集合。
IssuerSigningKeyResolverFunc<TokenValidationContext, IEnumerable<SecurityKey>, IEnumerable<SecurityKey>>用于解析发行者签名密钥的委托。
IssuerValidatorFunc<string, bool>验证令牌中的发行者(Issuer)声明的委托。
LifetimeValidatorFunc<DateTime?, DateTime?, bool>验证令牌生命周期的委托。
NameClaimTypestring用于识别名称声明的类型。
PropertyBagIDictionary<string, object>一个属性包,用于存储额外的配置信息。
RequireAudiencebool是否要求令牌中包含受众声明。
RequireExpirationTimebool是否要求令牌中包含过期时间声明。
RequireSignedTokensbool是否要求令牌必须被签名。
RoleClaimTypestring用于识别角色声明的类型。
SaveSigninTokenbool在身份验证成功后是否保存签名令牌。
TokenReaderITokenReader用于读取令牌的接口。
TokenReplayCacheITokenReplayCache用于防止令牌重放的缓存。
TokenReplayValidatorFunc<TokenReplayValidationResult>用于验证令牌是否被重放的委托。
TryAllIssuerSigningKeysbool是否尝试使用所有发行者签名密钥来验证签名。
TypeValidatorFunc<string, bool>验证令牌类型(如 JWT)的委托。
ValidateActorbool是否验证 Actor 声明。
ValidateAudiencebool是否验证受众声明。
ValidateIssuerbool是否验证发行者声明。
ValidateIssuerSigningKeybool是否验证发行者签名密钥。
ValidateLifetimebool是否验证令牌的生命周期。
ValidateSignatureLastbool是否在验证其他所有声明之后验证签名。
ValidateTokenReplaybool是否验证令牌是否被重放。
ValidateWithLKGbool是否使用最后已知良好的(Last Known Good)配置来验证令牌。
ValidAlgorithmsIEnumerable<string>接受的签名算法列表。
ValidAudiencestring单个有效的受众声明。
ValidAudiencesIEnumerable<string>有效的受众声明列表。
ValidIssuerstring单个有效的发行者声明。
ValidIssuersIEnumerable<string>有效的发行者声明列表。
ValidTypesIEnumerable<string>接受的令牌类型列表。

2.3 添加授权到指定控制器

builder.Services.AddAuthorization(configure =>
{
    configure.AddPolicy("Api", policy => policy.RequireClaim("AuthType", "Api"));
    configure.AddPolicy("User", policy => policy.RequireClaim("AuthType", "User"));

});

三、测试

3.1配置授权

[Route("api/[controller]")]

[ApiController]
public class UserController(IUserService _userService) : ControllerBase
{
        [Authorize(Policy = "User")] /*一定要添加授权码,不添加接口无法被保护*/
        [HttpPost("[action]")]
        public async Task<IActionResult> Updata(USER_Test users)
        {
            var result=await _userService.Updata(users);
            return Ok(result);
        }
}

我使用了更新用户名与密码的接口,然后正确的得到了未授权的401错误,说明我们的token已经配置成功啦!

3.2 使用token访问授权接口

登录获取token

使用接口测试工具填入token

访问授权更新接口

成功!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值