每個新技術許可權驗證都有一套機制,之前項目WebApi介面許可權驗證用的是Owin做為許可權驗證,而.netcore許可權限制使用的是IdentityServer4,採用JWT的方法驗證token. 首先使用Guget包管理添加IdentityServer4包的引用,如圖 生成token方法 創建JwtTo ...
每個新技術許可權驗證都有一套機制,之前項目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; }