.netcore2.1 使用IdentityServer4 生成Token验证

  每个新技术权限验证都有一套机制,之前项目WebApi接口权限验证用的是Owin做为权限验证,而.netcore权限限制使用的是IdentityServer4,采用JWT的方法验证token.

  • 首先使用Guget包管理添加IdentityServer4包的引用,如图

  

  • 生成token方法
/// <summary>
        /// 生成token
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="key">JwtKey</param>
        /// <returns></returns>
        public static string GenerateToken(string userId, string key)
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var keyBytes = System.Text.Encoding.Default.GetBytes(key);
            var authTime = DateTime.UtcNow;
            var expireaAt = authTime.AddHours(24);//token过期时间
            var timestamp = TimeStamp.GenerateTimeStamp(authTime);//生成日间戳
            var sign = MyUnity.GetMd5Upper32((userId + "&" + timestamp + "&" + key).ToUpper());
            var tokenDescriptor = new SecurityTokenDescriptor()
            {
                Subject = new ClaimsIdentity(new Claim[] {
                 new Claim(JwtClaimTypes.Audience,"api"),
                 new Claim(JwtClaimTypes.Issuer,"hengfeng"),
                 new Claim(JwtClaimTypes.Id,userId),
                 new Claim("timestamp",timestamp),
                 new Claim("sign",sign),
                   }),
                Expires = expireaAt,
                SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(keyBytes),
                SecurityAlgorithms.HmacSha256Signature)
            };
            var token = tokenHandler.CreateToken(tokenDescriptor);
            var tokenString = tokenHandler.WriteToken(token);
            return tokenString;
        }

 

   

  • 创建JwtTokenFilter过滤器
 public class JwtTokenFilter : ActionFilterAttribute
    {
        private readonly IConfiguration _config;
        public JwtTokenFilter(IConfiguration configuration)
        {
            _config = configuration;
        }
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            try
            {
                var token = context.HttpContext.Request.Headers["token"];
                var tokenHandler = new JwtSecurityTokenHandler();
                var jwtSecurityToken = tokenHandler.ReadJwtToken(token);
                var claims = jwtSecurityToken.Claims;
                var userid = claims.FirstOrDefault(m => m.Type == "id").Value;
                var sign = claims.FirstOrDefault(m => m.Type == "sign").Value;
                var expireaAt = claims.FirstOrDefault(m => m.Type == "exp").Value;
                var key = _config["jwt_key"];  
                var timestamp = claims.FirstOrDefault(m => m.Type == "timestamp").Value;
                var sign_new = MyUnity.GetMd5Upper32((userid + "&" + timestamp + "&" + key).ToUpper());
                if (!sign_new.Equals(sign, StringComparison.InvariantCultureIgnoreCase))
                {
                    context.Result = new JsonResult( "账号未登录");
                }
                else
                {
                    var expiresTime = TimeStamp.ConvertIntDateTime(expireaAt);
                    if ((DateTime.Now - expiresTime).Minutes > 0)
                    {
                        context.Result = new JsonResult("账号Token失效");
                    }
                }
            }
            catch (Exception ex)
            {
                context.Result = new JsonResult(ex.ToString());
            }
        }
    }
  • 在使用控制器中添加 [ServiceFilter(typeof(JwtTokenFilter))] 特性
     // GET: api/Default/5
        [HttpGet("{id}", Name = "Get")]
        [ServiceFilter(typeof(JwtTokenFilter))]
        public string Get(int id)
        {
            return "value";
        }
  • 如果该控制器不需要验证token,加上允许匿名访问特性即可
      [HttpPost]
        [AllowAnonymous]
        public void Post([FromBody] string value)
        {

        }

  最后:注意登录成功后,需要把生成的token返回给前端,前端再一次请求系统其它需要验证token的接口中,在head中加上token值。

 

用到的加密算法

  /// <summary>
       /// Md5 16位长度
       /// </summary>
       /// <param name="sValue"></param>
       /// <returns></returns>
        public static string GetMd5Upper16(string sValue)  
        {
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            string s = BitConverter.ToString(md5.ComputeHash(UTF8Encoding.Default.GetBytes(sValue)), 4, 8);
            s = s.Replace("-", "").ToUpper();
            return s;
        }
        /// <summary>
        ///  Md5 32位长度
        /// </summary>
        /// <param name="sValue"></param>
        /// <returns></returns>
        public static string GetMd5Upper32(string sValue)  
        {
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            string s = BitConverter.ToString(md5.ComputeHash(UTF8Encoding.Default.GetBytes(sValue)));
            s = s.Replace("-", "").ToUpper();
            return s;
        }

 生成 十位的时间戳

        /// <summary>
        /// 获取十位的时间戳
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static string GenerateTimeStamp(DateTime dt)
        {
            // Default implementation of UNIX time of the current UTC time  
            TimeSpan ts = dt.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt32(ts.TotalSeconds).ToString();
        }

 

posted @ 2019-04-30 17:16  低调码农哥!  阅读(2594)  评论(6编辑  收藏  举报