.NET Framework 中对webapi进行jwt验证
最近在项目中对webapi进行了jwt验证,做一个记录
- 有关于jwt生成和验证token的操作全部记录在jwthelper.cs文件中:
/// <summary> /// 授权JWT类 /// </summary> public class JwtHelper { public readonly string SecretKey = System.Configuration.ConfigurationManager.AppSettings["SecretKey"]; public readonly string AppId = System.Configuration.ConfigurationManager.AppSettings["AppId"]; public readonly string AppKey = System.Configuration.ConfigurationManager.AppSettings["AppKey"]; /// <summary> /// 创建Token 这里面可以保存自己想要的信息 /// </summary> /// <param name="user_id"></param> /// <param name="mobile"></param> /// <returns></returns> public string CreateToken(string user_id) { // 1. 定义需要使用到的Claims var claims = new Claim[] { new Claim("user_id", user_id), /* 可以保存自己想要信息,传参进来即可 new Claim("limit", "limit"), */ }; // 2. 从 appsettings.json 中读取SecretKey var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecretKey)); // 3. 选择加密算法 var algorithm = SecurityAlgorithms.HmacSha256; // 4. 生成Credentials var signingCredentials = new SigningCredentials(secretKey, algorithm); // 5. 根据以上,生成token var jwtSecurityToken = new JwtSecurityToken( issuer: AppId, //Issuer audience: AppKey, //Audience claims: claims, //Claims, notBefore: DateTime.Now, //notBefore expires: DateTime.Now.AddHours(1), //expires signingCredentials: signingCredentials //Credentials ); // 6. 将token变为string var token = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken); return token; } /// <summary> /// 根据token反向解析 /// </summary> /// <param name="token"></param> /// <returns></returns> public string GetInfoFromToken(string token = null) { if (token is null || token == "") return null; string tokenStr = token.Replace("Bearer ", ""); var handler = new JwtSecurityTokenHandler(); // string tokenStr = token; var payload = handler.ReadJwtToken(tokenStr).Payload; var claims = payload.Claims; var userid = claims.First(claim => claim.Type == "user_id")?.Value; return userid; } /// <summary> /// 从Token中获取用户身份 /// </summary> /// <param name="token"></param> /// <param name="securityKey">securityKey明文,Java加密使用的是Base64</param> /// <returns></returns> public ClaimsPrincipal GetPrincipal(string token) { try { string securityKey = SecretKey; token = token.Replace("Bearer ", ""); var handler = new JwtSecurityTokenHandler(); TokenValidationParameters tokenValidationParameters = new TokenValidationParameters { ValidateAudience = false, ValidateIssuer = false, ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(securityKey)), ValidateLifetime = false }; return handler.ValidateToken(token, tokenValidationParameters, out SecurityToken validatedToken); } catch (Exception ex) { return null; } } /// <summary> /// 校验Token /// </summary> /// <param name="token">token</param> /// <returns></returns> public bool CheckToken(string token) { var principal = GetPrincipal(token); if (principal is null) { return false; } return true; }
2. 控制器中添加获取token的方法
/// <summary> /// 获取Token /// </summary> /// <returns></returns> [System.Web.Http.HttpGet] public async Task<string> GetToken(string userid) { //参数验证等等.... if (string.IsNullOrEmpty(userid)) { return await Task.FromResult("参数异常!"); } //这里可以连接数据库做账号密码验证 //这里可以做Redis缓存验证等等 //这里获取Token var token = await Task.Run(() => { return _jwt.CreateToken(userid); }); return token; }
根据该访问获取到token
2. 自定义SaveImgAttribute,继承ActionFilterAttribute过滤器并重写OnActionExecuting()方法
public class SaveImgAttribute : ActionFilterAttribute { public readonly string SecretKey = System.Configuration.ConfigurationManager.AppSettings["SecretKey"]; public readonly string AppId = System.Configuration.ConfigurationManager.AppSettings["AppId"]; public readonly string AppKey = System.Configuration.ConfigurationManager.AppSettings["AppKey"]; // 调用方法前 public override void OnActionExecuting(ActionExecutingContext actionContext) { Jwt.JwtHelper _jwt = new Jwt.JwtHelper(); var token = ""; if (actionContext.HttpContext.Request.Headers.AllKeys.Contains("Authorization")) { int index = actionContext.HttpContext.Request.Headers.AllKeys.Select((a, i) => i).Where(i => actionContext.HttpContext.Request.Headers.AllKeys[i] == "Authorization").FirstOrDefault(); token = actionContext.HttpContext.Request.Headers[index]; } if (token == null || token == "") { var Auth = new { Status = 401, Message = "身份验证失败" }; actionContext.Result = new ContentResult { ContentType = "application/json", Content = JsonConvert.SerializeObject(Auth) }; return; } bool isOK = _jwt.CheckToken(token); if (!isOK) { var Auth = new { Status = 401, Message = "身份验证失败" }; actionContext.Result = new ContentResult { ContentType = "application/json", Content = JsonConvert.SerializeObject(Auth) }; return; } var userid = _jwt.GetInfoFromToken(token); base.OnActionExecuting(actionContext); } }
3. 在控制器方法上加上[SaveImg]特性即可,每次调用对应方法的时候都会在SaveImgAttribute中进行 token验证
[SaveImg] [System.Web.Http.HttpPost] public async Task<JsonResult> SaveFileToOSS([FromBody] RequestBody request) {.....}
将GetToken()获取到的token添加到http请求头中(key:Authorization)(value:Bearer+空格+token)再进行对应方法的请求