先随便贴点代码

1、引用JwtBearer Nuget包

ASP.NETCore-中间件Middleware(六)_认证+授权中间件-JWT_System

2、Program.cs启用JWT
using fly_chat1_net7.Middlewares;
using fly_chat1_net7.Middlewares.UserLoginAuthorizations;
using fly_webapi.IService.UserService.LoginAuthorization;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.CookiePolicy;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using System;
using System.Net.Http;
using System.Text;
using System.Threading;

namespace fly_chat1_net7
{
    public class Program
    {
        public static void Main(string[] args)
        {
            // try前也可能报错,但是错误是可控的。实际项目中使用时可以再加个try,只记录日志到文件中。
            var configuration = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())  // 设置“configuration”的查找目录为程序目录
                .AddJsonFile("appsettings.json")  // 设置“configuration”的读取文件
                .Build();  // 获取配置
            
                var builder = WebApplication.CreateBuilder(args);
                // 中间件知识https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?view=aspnetcore-6.0#order

                #region 容器Services
                builder.Services.AddControllers();            // 添加Controller
                builder.Services.AddHttpContextAccessor();    // 操作Http上下文;比如:AOP里面可以获取IOC对象
                builder.Services.AddEndpointsApiExplorer();   // ASP.NET Core自身提供;Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle

                #region JWT
                IUserAuthorization userAuthorization = new UserAuthorization_JWT();
                builder.Services.AddSingleton(userAuthorization);  // JWT认证中间件
                builder.Services.AddAuthentication(options => {
                    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                })
                    .AddJwtBearer(options => {  // 配置Authentication用的JWT
                        options.TokenValidationParameters = new TokenValidationParameters
                        {
                            ValidateIssuerSigningKey = true,
                            ValidIssuer = configuration["Jwt:Issuer"],
                            ValidAudience = configuration["Jwt:Audience"],
                            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["Jwt:SecurityKey"] ?? "a48fafeefd334237c2ca207e842afe0b")),
                            ClockSkew = TimeSpan.Zero
                        };
                    });
                #endregion JWT
                #endregion 容器Services

                var app = builder.Build();
            
                app.UseHttpsRedirection();
                app.UseStaticFiles();  // 在UseRouting()前
                app.UseRouting();

                app.UseAuthentication();  // 认证
                app.UseAuthorization();   // 授权

                app.MapControllers();
                app.Run();
        }
    }
}
  • 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.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
3、JWT的配置(appsettings.json中)
{
  "Jwt": {
    "Issuer": "yunyistars.com", // token 的颁发者
    "Audience": "yunyistars.com", // token 的接收者
    "SecurityKey": "a48fafeefd334237c2ca207e842afe0b", // 加密 token的key值(32位)
    "ExpireMinutes": "20" // token 的过期时间(单位分钟)
  },
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
4、JWT登录认证中间件
using fly_webapi.IService.UserService.LoginAuthorization;
using fly_webapi.ViewModel.Users;
using Microsoft.Extensions.Primitives;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Net;
using System.Security.Claims;
using System.Text;

namespace fly_chat1_net7.Middlewares.UserLoginAuthorizations
{
    /// <summary>
    /// 用户认证_JWT
    /// </summary>
    public class UserAuthorization_JWT : IUserAuthorization
    {
        /// <summary>
        /// 配置文件
        /// </summary>
        IConfigurationRoot _configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())  // 设置“configuration”的查找目录为程序目录
.AddJsonFile("appsettings.json")  // 设置“configuration”的读取文件
.Build();  // 获取配置

        /// <summary>
        /// 生成用户信息-创建Token
        /// 从JWT中读取信息var name = HttpContext.User.FindFirst(JwtRegisteredClaimNames.Name)?.Value;
        /// </summary>
        /// <param name="userInfoVModel">用户信息</param>
        public AuthorizationObject Create(UserInfoVModel userInfoVModel)
        {
            DateTime expiresAt = DateTime.UtcNow.AddMinutes(Convert.ToDouble(_configuration["Jwt:ExpireMinutes"]));  // token 的过期时间

            // 签发一个加密后的用户信息凭证ClaimsPrincipal,用来标识用户的身份
            IEnumerable<Claim> claims = new Claim[] {  // 将用户信息添加到 Claim 中
                new Claim(ClaimTypes.Name,userInfoVModel.UserName),            // 用户名
                new Claim(ClaimTypes.Role,userInfoVModel.RoleId.ToString()),   // 角色ID
                new Claim(ClaimTypes.MobilePhone,userInfoVModel.MobilePhone),  // 手机号
                new Claim(ClaimTypes.Email,userInfoVModel.Email),              // 邮箱号
                new Claim(ClaimTypes.Expiration,expiresAt.ToString())  // 过期日期
            };
            //var identity = new ClaimsIdentity(claims, JwtBearerDefaults.AuthenticationScheme);
            //_httpContextAccessor.HttpContext.SignInAsync(JwtBearerDefaults.AuthenticationScheme, new ClaimsPrincipal(identity));

            // 设置 SecurityTokenDescriptor
            SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:SecurityKey"] ?? "a48fafeefd334237c2ca207e842afe0b"));  // 加密 token 的key值
            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(claims),       // 用户信息
                Issuer = _configuration["Jwt:Issuer"],      // Jwt token 的签发者
                Audience = _configuration["Jwt:Audience"],  // Jwt token 的接收者
                Expires = expiresAt,                        // 过期时间
                SigningCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256),  //创建 token
            };

            JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
            var token = tokenHandler.CreateToken(tokenDescriptor);  // 创建Token

            //存储 Token 信息
            var jwt = new AuthorizationObject
            {
                //UserId = userInfoVModel.UserId,  // 用户的Id
                AuthorizationType=AuthorizationObjectType.Jwt_Microsoft,  // AuthorizationObject类型为Jwt_Microsoft
                Token = tokenHandler.WriteToken(token),                   // 获取创建完的Token
                Expiration= expiresAt                                     // 过期时间
            };

            // 把Token存放到MemoryCache或Redis中

            return jwt;
        }

        /// <summary>
        /// 停用Token
        /// </summary>
        /// <param name="token">Token</param>
        /// <returns></returns>
        public async Task<bool> DeactivateAsync(string token)
        {
            // 修改Token信息

            // 把Token从MemoryCache或Redis中删除

            return true;
        }

        /// <summary>
        /// 停用当前Token
        /// </summary>
        /// <param name="token">Token</param>
        /// <returns></returns>
        public async Task<bool> DeactivateCurrentAsync(HttpContext httpContext) => await DeactivateAsync(GetCurrentAsync(httpContext));

        /// <summary>
        /// 刷新 Token
        /// </summary>
        /// <param name="token">Token</param>
        /// <param name="dto">用户信息数据传输对象</param>
        /// <returns></returns>
        public async Task<AuthorizationObject> RefreshAsync(string token, UserInfoVModel userInfoVModel)
        {
            var jwtOld =await IsActiveAsync(token);  // 判断 Token 是否有效
            if (!jwtOld)
            {
                throw new Exception("未获取到当前用户信息!");
            }

            // 将旧的Token从MemoryCache或Redis中删除


            var jwt = Create(userInfoVModel);

            // 将新的Token存放到MemoryCache或Redis中


            return jwt; 
        }

        /// <summary>
        /// 判断 Token 是否有效
        /// </summary>
        /// <param name="token">Token</param>
        /// <returns></returns>
        public async Task<bool> IsActiveAsync(string token)
        {
            // 检验1-Token是否有效(Token格式正常+未过期)

            // 检验2-MemoryCache或Redis中是否存在(可以防伪造Token)

            return true;
        }

        /// <summary>
        /// 判断当前 Token 是否有效
        /// </summary>
        /// <returns></returns>
        public async Task<bool> IsActiveCurrentAsync(HttpContext httpContext)=> await IsActiveAsync(GetCurrentAsync(httpContext));

        #region private方法
        /// <summary>
        /// 获取 HTTP 请求的 Token 值
        /// </summary>
        /// <returns></returns>
        private string GetCurrentAsync(HttpContext httpContext)
        {
            //http header
            var authorizationHeader = httpContext.Request.Headers["authorization"];

            //token
            return authorizationHeader == StringValues.Empty? string.Empty: authorizationHeader.Single().Split(" ").Last();  // bearer tokenvalue
        }
        #endregion private方法
    }
}
  • 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.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.

作者:꧁执笔小白꧂