# 首先安装 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] 用来鉴权

更新于 阅读次数

请我喝茶~( ̄▽ ̄)~*

Tianci 微信支付

微信支付

Tianci 支付宝

支付宝