首先安装jwt所需的Nuget包

Microsoft.AspNetCore.Authentication.JwtBearer
<!-- Swagger授权扩展包 -->
Swashbuckle.AspNetCore.Filters

创建一个类里面写两个方法用来配置Swagger和JWT

/// <summary>
/// Jwt以及Swagger扩展配置
/// </summary>
public static class JwtExtension
{
    /// <summary>
    /// Jwt配置授权
    /// </summary>
    /// <param name="services"></param>
    /// <param name="builder"></param>
    /// <returns></returns>
    public static AuthenticationBuilder MyAddAuthentication(this IServiceCollection services, WebApplicationBuilder builder)
    {
        return services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,// 是否验证Issuer
                    ValidateAudience = true,// 是否验证Audience
                    ValidateLifetime = true,// 是否验证失效时间
                    ClockSkew = TimeSpan.FromSeconds(30),// 有效时间
                    ValidateIssuerSigningKey = true,// 是否验证SecurityKey
                    ValidAudience = builder.Configuration.GetSection("JWT:Audience").Value,// Audience
                    ValidIssuer = builder.Configuration.GetSection("JWT:Issuer").Value,// Issuer,这两项和前面签发jwt的设置一致
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration.GetSection("JWT:SecurityKey").Value))// SecurityKey
                };
                options.Events = new JwtBearerEvents
                {
                    // 此处为权限验证失败后触发的事件
                    OnChallenge = context =>
                    {
                        // 此处代码为终止.Net Core默认的返回类型和数据结果,这个很重要哦,必须
                        context.HandleResponse();
                        // 自定义自己想要返回的数据结果,我这里要返回的是Json对象,通过引用Newtonsoft.Json库进行转换
                        var payload = JsonConvert.SerializeObject(new Result(DataModel.Enum.HttpCode.Unauthorized, DataModel.Enum.HttpMessage.Unauthorized));
                        // 自定义返回的数据类型
                        context.Response.ContentType = "application/json";
                        // 自定义返回状态码,默认为401 我这里改成 200
                        context.Response.StatusCode = 200;
                        // 输出Json数据结果
                        context.Response.WriteAsync(payload);
                        return Task.FromResult(0);
                    },
                    // 权限不够,例如角色组Role无该权限
                    OnForbidden = context =>
                    {
                        // 自定义自己想要返回的数据结果,我这里要返回的是Json对象,通过引用Newtonsoft.Json库进行转换
                        var payload = JsonConvert.SerializeObject(new Result(DataModel.Enum.HttpCode.Forbidden, DataModel.Enum.HttpMessage.Forbidden));
                        // 自定义返回的数据类型
                        context.Response.ContentType = "application/json";
                        // 自定义返回状态码,默认为403 我这里改成 200
                        context.Response.StatusCode = 200;
                        // 输出Json数据结果
                        context.Response.WriteAsync(payload);
                        return Task.FromResult(0);
                    }
                };
            });
    }

    /// <summary>
    /// Swagger配置信息
    /// </summary>
    /// <param name="services"></param>
    /// <returns></returns>
    public static IServiceCollection MyAddSwaggerGen(this IServiceCollection services)
    {
        return services.AddSwaggerGen(c =>
        {
            // Swagger文档版本控制(ApiExplorerSettings中GroupName需要和ApiVersion枚举定义一致)
            typeof(DataModel.Enum.ApiVersion).GetEnumNames().ToList().ForEach(name =>
            {
                c.SwaggerDoc(name, new OpenApiInfo { Title = "DotNET6原生API", Version = name, Description = "<b><a href='https://gitee.com/lovetianci/TianciDotNET6API'>项目地址</a><b>" });
            });
            // 控制器注释(需在对应项目>属性>输出>文档文件:生成包含API文档的文件√)
            c.IncludeXmlComments(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TianciDotNET6API.xml"), true);
            // 实体类注释(需在对应项目>属性>输出>文档文件:生成包含API文档的文件√)
            c.IncludeXmlComments(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DataModel.xml"), true);

            // Summary注释显示授权组名称信息
            c.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();

            // 加这个带锁,false为请求接口未授权将不会显示返回值例如Forbidden
            c.OperationFilter<SecurityRequirementsOperationFilter>(false);

            var security = new OpenApiSecurityScheme
            {
                In = ParameterLocation.Header,
                Type = SecuritySchemeType.ApiKey,
                // 如果是ApiKey则需要输入Bearer token(中间有空格)
                // 因为Scheme填写了Bearer,所以Swagger只需输入token即可(2022年8月29日)
                // 如果是http则直接输入token
                Description = "直接在下框中输入token<br/><b>授权地址:/api/Login/Login</b>",
                Name = "Authorization",
                Scheme = "Bearer",
                BearerFormat = "JWT"
            };
            // oauth2唯一不可变
            c.AddSecurityDefinition("oauth2", security);

            // 添加全局安全要求,所需方案的字典(逻辑与)密钥必须对应于通过 AddSecurityDefinition 定义的方案
            // 如果方案是oauth2类型,则值是范围列表,否则必须是空数组
            //c.AddSecurityRequirement(new OpenApiSecurityRequirement { { security, new string[] { } } });
            // 请求头过滤,上面写了鉴权失败返回值所以这不需要
            //c.OperationFilter<AddResponseHeadersFilter>();
        });
    }
}

配置文件appsetting.json中配置对应的密钥字段(模拟数据)

"JWT": {
    "Issuer": "Client",
    "Audience": "Server",
    "SecurityKey": "EF1DA5B7-C4FA-4240-B997-7D1701BF9BE2"
},

将服务添加到容器

var builder = WebApplication.CreateBuilder(args);

// Swagger配置
builder.Services.MyAddSwaggerGen();

// 注册jwt
builder.Services.MyAddAuthentication(builder);

配置HTTP请求管道

var app = builder.Build();

// 认证
app.UseAuthentication();

// 授权
app.UseAuthorization();

// 开启Swagger
app.UseSwagger();
app.UseSwaggerUI(c =>
{
    // Swagger文档版本控制
    typeof(DataModel.Enum.ApiVersion).GetEnumNames().ToList().ForEach(name =>
    {
        c.SwaggerEndpoint($"/Swagger/{name}/Swagger.json", $"{name}");

        // 设置首页index为Swagger
        c.RoutePrefix = string.Empty;
        // 设置网页Title
        c.DocumentTitle = "TianciDotNET6API接口文档";
        // 设置为none默认可折叠所有方法
        c.DocExpansion(DocExpansion.None);
        // 设置为-1 可不显示models
        c.DefaultModelsExpandDepth(-1);
    });
});

登录获取Token的方法可以简单定义一个

_configuration为注入的IConfiguration接口

string userToken = string.Empty;
var claims = new[]
{
    new Claim(ClaimTypes.Name, "UserName"),
    new Claim(ClaimTypes.Role, "RoleName"),
    new Claim(JwtRegisteredClaimNames.Sub,"UserName"),
    new Claim(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString())
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration.GetSection("JWT:SecurityKey").Value));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken
(
    issuer: _configuration.GetSection("JWT:Issuer").Value,// 签发人
    audience: _configuration.GetSection("JWT:Audience").Value,// 受众人
    claims: claims,
    expires: DateTime.Now.AddMinutes(30),//过期时间
    signingCredentials: creds
);
userToken = new JwtSecurityTokenHandler().WriteToken(token);

最后控制器添加[Authorize]用来鉴权


被这风吹散的人说Ta爱的不深,被这雨淋湿的人说Ta不会冷