zoukankan      html  css  js  c++  java
  • ASP.NET Core-自定义Jwt token验证(ISecurityTokenValidator)

    Core为我们提供了自定义token验证的接口,当我们需要使用自己的方式验证token时可以使用。
    比如Jwt只能数据签名,不能加密。当需要校验加密的jwt token。在登录时将jwt token加密后传给客户端,客户端回传token。这时需要我们自定义token校验。

    自定义token校验,实现ISecurityTokenValidator接口

        /// <summary>
        /// 自定义token校验
        /// </summary>
        public class MyTokenValidator : ISecurityTokenValidator
        {
            public int MaximumTokenSizeInBytes { get; set; }
    
            public bool CanReadToken(string securityToken)
            {
                return true;
            }
            public bool CanValidateToken
            {
                get
                {
                    return true;
                }
            }
    
            //验证token
            public ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken)
            {
                string jwtToken = AESCryptoHelper.Decrypt(securityToken);
                ClaimsPrincipal principal = new JwtSecurityTokenHandler().ValidateToken(jwtToken, validationParameters, out validatedToken);
                return principal;
            }
        }
    

    配置文件中添加配置:

      "JwtTokenOptions": {
        "Issuer": "FAN.Issuer",
        "ValidateIssuer": true,
        "Audience": "FAN.Audience",
        "ValidateAudience": true,
        "RawSigningKey": "11111111-1111-1111-1111-111111111111",/*签名秘钥*/
        "ValidateIssuerSigningKey": true,
        "ValidateLifetime": false,
        "RequireExpirationTime": false,
        "JwtExpiresInMinutes": 6000,
        "ValidateIntervaltime": true,
        "IntervalExpiresInMinutes": 3000
      }
    

    Startup.cs添加如下内容:

    public void ConfigureServices(IServiceCollection services)
            {
                services.AddScoped<TokenBuilder>();
                services.Configure<JwtTokenOptions>(Configuration.GetSection("JwtTokenOptions"));
                JwtTokenOptions tokenOptions = Configuration.GetSection("JwtTokenOptions").Get<JwtTokenOptions>();
    
                services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                      //开启Bearer服务认证
                      .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
                      {
                          options.SaveToken = true;
                          options.TokenValidationParameters = tokenOptions.ToTokenValidationParams();
                          options.SecurityTokenValidators.Clear();
                          options.SecurityTokenValidators.Add(new MyTokenValidator());
                      });
             }
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                app.UseAuthentication();
            }
    

    User:用户信息

        /// <summary>
        /// 登录用户信息
        /// </summary>
        public class User
        {
            public int UserID { get; set; }
            public string Email { get; set; }
    
            public string Name { get; set; }
            public string Role { get; set; }
    
    
            public User(int userID, string name, string email, string role)
            {
                this.UserID = userID;
                this.Name = name;
                this.Email = email;
                this.Role = role;
            }
        }
    

    TokenBuilder:用于创建jwt token

    /// <summary>
        /// token创建
        /// </summary>
        public class TokenBuilder
        {
            private JwtTokenOptions _tokenOptions = null;
            public TokenBuilder(IOptions<JwtTokenOptions> tokenOptions)
            {
                this._tokenOptions = tokenOptions.Value;
            }
            /// <summary>
            /// 创建加密JwtToken
            /// </summary>
            /// <param name="user"></param>
            /// <returns></returns>
            public string CreateJwtToken(User user)
            {
                var claimList = this.CreateClaimList(user);
                JwtSecurityToken jwtSecurityToken = new JwtSecurityToken(
                    issuer: this._tokenOptions.Issuer
                    , audience: this._tokenOptions.Audience
                    , claims: claimList
                    //, notBefore: utcNow
                    , expires: DateTime.Now.AddDays(3)
                    , signingCredentials: new SigningCredentials(this._tokenOptions.SigningKey, SecurityAlgorithms.HmacSha256)
                );
                string jwtToken = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);
                //加密jwtToken
                jwtToken = AESCryptoHelper.Encrypt(jwtToken);
                return jwtToken;
            }
    
            /// <summary>
            /// 创建包含用户信息的CalimList
            /// </summary>
            /// <param name="authUser"></param>
            /// <returns></returns>
            private List<Claim> CreateClaimList(User authUser)
            {
                //身份单元项项集合
                List<Claim> claimList = new List<Claim>()
                        {
                            new Claim(type: ClaimTypes.Email, value: authUser.Email), //身份单元项
                            new Claim(type: ClaimTypes.Name, value: authUser.Name),
                            new Claim(type: ClaimTypes.NameIdentifier, value: authUser.UserID.ToString()),
                            new Claim(type: ClaimTypes.Role, value: authUser.Role ?? string.Empty)
                        };
                return claimList;
            }
        }
    

    AESCryptoHelper:使用AES对jwttoken的加密解密

        /// <summary>
        /// AES加密解密
        /// </summary>
        public class AESCryptoHelper
        {
            /// <summary>
            /// AES加密解密Key,Key必须十六位
            /// </summary>
            private static readonly string AESKey = "1111111111111111";
            /// <summary>
            ///  AES 加密
            /// </summary>
            /// <param name="plainText"></param>
            /// <returns></returns>
            public static string Encrypt(string plainText)
            {
                return Encrypt(plainText, AESKey);
            }
            /// <summary>
            ///  AES 加密
            /// </summary>
            /// <param name="plainText"></param>
            /// <param name="key">密码必须是16位,否则会报错哈</param>
            /// <returns></returns>
            public static string Encrypt(string plainText, string key)
            {
                string result = null;
                if (string.IsNullOrEmpty(plainText))
                {
                    return result;
                }
                byte[] plainTextArray = Encoding.UTF8.GetBytes(plainText);
                using (MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider())
                {
                    using (RijndaelManaged rijndaelManaged = new RijndaelManaged
                    {
                        Key = provider.ComputeHash(Encoding.UTF8.GetBytes(key)),
                        //Key = Encoding.UTF8.GetBytes(key),
                        Mode = CipherMode.ECB,
                        Padding = PaddingMode.PKCS7
                    })
                    {
                        using (ICryptoTransform cryptoTransform = rijndaelManaged.CreateEncryptor())
                        {
                            byte[] resultArray = cryptoTransform.TransformFinalBlock(plainTextArray, 0, plainTextArray.Length);
                            result = Convert.ToBase64String(resultArray, 0, resultArray.Length);
                            Array.Clear(resultArray, 0, resultArray.Length);
                            resultArray = null;
                        }
                    }
                }
                Array.Clear(plainTextArray, 0, plainTextArray.Length);
                plainTextArray = null;
                return result;
            }
            /// <summary>
            ///  AES 解密
            /// </summary>
            /// <param name="encryptText"></param>
            /// <returns></returns>
            public static string Decrypt(string encryptText)
            {
                return Decrypt(encryptText, AESKey);
            }
            /// <summary>
            ///  AES 解密
            /// </summary>
            /// <param name="encryptText"></param>
            /// <param name="key">密码必须是16位,否则会报错哈</param>
            /// <returns></returns>
            public static string Decrypt(string encryptText, string key)
            {
                string result = null;
                if (string.IsNullOrEmpty(encryptText))
                {
                    return result;
                }
                byte[] encryptTextArray = Convert.FromBase64String(encryptText);
                using (MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider())
                {
                    using (RijndaelManaged rijndaelManaged = new RijndaelManaged
                    {
                        Key = provider.ComputeHash(Encoding.UTF8.GetBytes(key)),
                        //Key = Encoding.UTF8.GetBytes(key),
                        Mode = CipherMode.ECB,
                        Padding = PaddingMode.PKCS7
                    })
                    {
                        using (ICryptoTransform cryptoTransform = rijndaelManaged.CreateDecryptor())
                        {
                            byte[] resultArray = cryptoTransform.TransformFinalBlock(encryptTextArray, 0, encryptTextArray.Length);
                            result = Encoding.UTF8.GetString(resultArray);
                            Array.Clear(resultArray, 0, resultArray.Length);
                            resultArray = null;
                        }
                    }
                }
                Array.Clear(encryptTextArray, 0, encryptTextArray.Length);
                encryptTextArray = null;
                return result;
            }
        }
    

    控制器:

        [Route("api/[controller]/[action]")]
        [ApiController]
        public class ValuesController : ControllerBase
        {
            private TokenBuilder _tokenBuilder = null;
            public ValuesController(TokenBuilder tokenBuilder)
            {
                this._tokenBuilder = tokenBuilder;
            }
            /// <summary>
            /// 登录,生成加密token
            /// </summary>
            /// <returns></returns>
            [HttpGet]
            public ActionResult<string> Login()
            {
                //省略登录逻辑。。。。
                var user = new User(1, "fan", "410577910@qq.com", "admin");
                string signToken = this._tokenBuilder.CreateJwtToken(user);
                return signToken;
            }
            /// <summary>
            /// 创建订单,需要校验token
            /// </summary>
            /// <returns></returns>
            [Authorize]
            [HttpPost]
            public ActionResult<string> CreateOrder()
            {
                if (base.User.Identity.IsAuthenticated)
                {
                    string userName = base.User.Identity.Name;
                }
                //省略创建订单逻辑。。。
                return "生成订单成功";
            }
        }
    

    测试

    登录:(获取token)

    http://localhost:5000/api/values/CreateOrder

    创建订单:(带上token,才能授权通过)

    http://localhost:5000/api/values/CreateOrder POST
    Headers添加:
    Key: Authorization
    Value: Bearer 2FrDOaIT8r9n7axl4ARhe2dp7S7bWS5+eCcErbkeIIzVbutYr+LmMI1HBEWCLwgwS80adJlwDGW9iNtL2Kp4y+twxHmEpPJfhmg8X1uzgYReh6Nd7XcJmQh9zXvma9gfySU8DcEOijD79wellmRqPNh8ZYX7C0DqKx55L8DVgkJ4emOHIyni/V7qs3xqgU6RstCCxOAI4tHS7v67jmtQJks2x88iBntAJWsPwr7jRChvdWXHpsMeOzyZDjEwiT/XZIFHwB6wyUOfGqqkpdj3s36XwaKEvEBJzwSL2LCUEpMJUr7SQ0r4ZJNnPEBsFoiA/s35nbhgt9OU5w4Z+9MUJ2hBW/eTRlhwtcUR48nitE+PyJS9Ipan+wngvKkkX64BU0l4aLQ9b+REmjf9NZ1RD1UGCL2bmP5XDeoHtYM8uEGYCXu4vvZ1C16oy7AJv/PEEUtL1WNEwJ0Pf9A3DV0o0UxR1q1T5x5nFHftmUu/wrgL2R6GJkUKvWOFWJgAILRk1jHd6HueuqTdTZWdPIDmUH6XwaKEvEBJzwSL2LCUEpMATTE2c3Sw+06USRWWJ3+pIYWS7pM632cOahyPj5iyAihGleXc3bFgjTH/9zlUnJAz3FTrFdRLjj4Vy/UTQDwUKLZEcPWXcYFTPtfuMuR1rwrzIXJOa8ywA/qdbn0XTHtCbTPTHADBaqPEzK8NxMQdCrtgfuCjJ4kPrmVxOaf784RiHgDmcvJ+2Xtazf09hYo+gKtSy8xLTktDZHxfniAtfZP8QU18rpGNsOcKl/E7rA==

  • 相关阅读:
    算法
    nginx配置https
    IE中JS跳转丢失referer的问题
    js 调用字符串类型的 js语句
    移动端iOS中input聚焦不灵敏
    上传图片转换格式为base64并预览
    转:手机号脱敏
    转:Lodash之throttle(节流)与debounce(防抖)总结
    转:tinyMCE中图片的自定义上传
    chrome input 输入框去掉黄色
  • 原文地址:https://www.cnblogs.com/fanfan-90/p/13302205.html
Copyright © 2011-2022 走看看