考慮到很多公司目前並沒有切換到.netcore,所有本文嘗試使用.netframework下的webapi
首先使用Nuget 安裝 jwt包
安裝完成后,創建 jwt的幫助類
public class JwtToken { static IJwtAlgorithm algorithm = new HMACSHA256Algorithm();//HMACSHA256加密 static IJsonSerializer serializer = new JsonNetSerializer();//序列化和反序列 static IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();//Base64編解碼 static IDateTimeProvider provider = new UtcDateTimeProvider();//UTC時間獲取 const string secret = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4aKpVo2OHXPwb1R7duLgg";//服務端 /// <summary> /// 創建token /// </summary> /// <param name="payload">字典對象</param> /// <returns></returns> public static string CreateJWT(Dictionary<string, object> payload) { IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder); return encoder.Encode(payload, secret); } /// <summary> /// 驗證token /// </summary> /// <param name="token">token值</param> /// <param name="payload">token還原后的字典</param> /// <param name="message">驗證結果</param> /// <returns></returns> public static bool ValidateJWT(string token, out string payload, out string message) { bool isValidted = false; payload = ""; try { IJwtValidator validator = new JwtValidator(serializer, provider);//用於驗證JWT的類 // IJwtAlgorithm algorithm= new HMACSHA256Algorithm(); IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder,algorithm);//用於解析JWT的類 payload = decoder.Decode(token, secret, verify: true); isValidted = true; message = "驗證成功"; } catch (TokenExpiredException)//當前時間大於負載過期時間(負荷中的exp),會引發Token過期異常 { message = "過期了!"; } catch (SignatureVerificationException)//如果簽名不匹配,引發簽名驗證異常 { message = "簽名錯誤!"; } return isValidted; } }
然后創建相關的Model
public class LoginResult { public bool Success { get; set; } public string Token { get; set; } public string Message { get; set; } }
創建獲取token的api
public LoginResult Post([FromBody]LoginRequest request) { LoginResult rs = new LoginResult(); //這是是獲取用戶名和密碼的,這里只是為了模擬 if (request.UserName == "admin" && request.Password == "123456") { try { var payload = new Dictionary<string, object> { { "username","admin"},//發行人 { "exp", DateTimeOffset.UtcNow.AddSeconds(100).ToUnixTimeSeconds() },//到期時間 }; rs.Token = JwtToken.CreateJWT(payload); rs.Success = true; } catch (Exception ex) { rs.Message = ex.Message; rs.Success = false; } } else { rs.Message = "fail"; rs.Success = false; } return rs; }
創建驗證token的filter
public class ApiAuthorizeAttribute : AuthorizationFilterAttribute { public override void OnAuthorization(HttpActionContext actionContext) { var attr = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().OfType<AllowAnonymousAttribute>(); bool isAnonymous = attr.Any(a => a is AllowAnonymousAttribute); if (!isAnonymous) { var rq= actionContext.Request.Properties; var authorization = actionContext.Request.Headers.Authorization; if (authorization==null) { actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized); } else { string ResultMessage;//需要解析的消息 string Payload;//獲取負載 var result = JwtToken.ValidateJWT(authorization.Scheme, out Payload, out ResultMessage); //TokenManager.ValidateToken(authorization.Scheme); if (!result) { actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized); } } } }
最后把特性加到需要需要驗證的Action上
// GET: User [ApiAuthorize] public string Get() { return $"獲取到了"; }
然后進行測試,首先獲取token
調用接口,並傳入token值
如果不傳入token值,那么會報401錯誤
當然了,那個401錯誤其實是在filter里自己定義的,你改成別的狀態碼也是可以的,不過盡量還是要遵循國際慣例了