JSON Web Token(縮寫 JWT)是目前最流行的跨域認證解決方案,本文介紹它的用法。
1、nuget中安裝jwt
2、新建3個實體
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace Web.Models { /// <summary> /// 登錄後的口令信息 /// </summary> public class LoginResult { /// <summary> /// 是否成功 /// </summary> public bool Success { get; set; } /// <summary> /// 令牌 /// </summary> public string Token { get; set; } /// <summary> /// 錯誤信息 /// </summary> public string Message { get; set; } } public class LoginRequest { public string UserName { get; set; } public string Password { get; set; } } /// <summary> /// 身份驗證信息(模擬JWT的payload) /// </summary> public class AuthInfo { /// <summary> /// 用戶名 /// </summary> public string UserName { get; set; } /// <summary> /// 角色 /// </summary> public List<string> Roles { get; set; } /// <summary> /// 是否管理員 /// </summary> public bool IsAdmin { get; set; } /// <summary> /// 過期時間 /// </summary> public DateTime? ExpiryDateTime { get; set; } } }
3、新建過濾器
using JWT; using JWT.Serializers; using Model; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web; using System.Web.Http; using System.Web.Http.Controllers; using Web.Models; namespace Web.Filter { /// <summary> /// webapi權限驗證(jwt) /// </summary> public class ApiAuthorizeAttribute : AuthorizeAttribute { /// <summary> /// 指示指定的控件是否已獲得授權 /// </summary> /// <param name="actionContext"></param> /// <returns></returns> protected override bool IsAuthorized(HttpActionContext actionContext) { var authHeader = from t in actionContext.Request.Headers where t.Key == "auth" select t.Value.FirstOrDefault(); if (authHeader != null) { string token = authHeader.FirstOrDefault(); if (!string.IsNullOrEmpty(token)) { try { //string secureKey = System.Configuration.ConfigurationManager.AppSettings["SecureKey"]; const string secret = "webapi";//隨意設置,或者放入web.config中 //secret需要加密 IJsonSerializer serializer = new JsonNetSerializer(); IDateTimeProvider provider = new UtcDateTimeProvider(); IJwtValidator validator = new JwtValidator(serializer, provider); IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder(); IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder); var json = decoder.DecodeToObject<AuthInfo>(token, secret, verify: true); if (json != null) { //判斷口令過期時間 if (json.ExpiryDateTime < DateTime.Now) { return false; } //供controller調用: //AuthInfo authInfo = this.RequestContext.RouteData.Values["auth"] as AuthInfo; //authInfo.Roles actionContext.RequestContext.RouteData.Values.Add("auth", json); return true; } return false; } catch (Exception ex) { return false; } } } return false; } /// <summary> /// 處理授權失敗的請求 /// </summary> /// <param name="actionContext"></param> protected override void HandleUnauthorizedRequest(HttpActionContext actionContext) { //var erModel = new //{ // Success = "false", // ErrorCode = "401" //}; ResponseMessage res = new ResponseMessage(401, "無訪問權限"); actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.OK, res, "application/json"); } } }
4、登錄api
public LoginResult Login([FromBody]LoginRequest request) { LoginResult rs = new LoginResult(); //這是是獲取用戶名和密碼的,這裏只是爲了模擬 if (request.UserName == "zhangsan" && request.Password == "123456") { AuthInfo info = new AuthInfo { UserName = "zhangsan", Roles = new List<string> { "Admin", "Manage" }, IsAdmin = true, ExpiryDateTime = DateTime.Now.AddHours(2) }; try { const string secret = "webapi";//口令加密祕鑰 //secret需要加密 IJwtAlgorithm algorithm = new HMACSHA256Algorithm();//加密方式 IJsonSerializer serializer = new JsonNetSerializer();//序列化Json IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();//base64加解密 IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);//JWT編碼 var token = encoder.Encode(info, secret);//生成令牌 rs.Message = "成功"; rs.Token = token; rs.Success = true; } catch (Exception ex) { rs.Message = ex.Message; rs.Success = false; } } else { rs.Message = "用戶信息爲空"; rs.Success = false; } return rs; }
5、獲取數據api
[HttpGet] [ApiAuthorize] public ResponseMessage GetData(int id) { //do }
6、前端登錄
//login $("#btn_login").click(function () { $.ajax({ url: '/api/Users/login', type: "post", data: { UserName: "zhangsan", Password: "123456"}, success: function (data) { console.log(data) if (data.Success) { //演示,將token保存在全局變量中。 //實現項目中應該保存在cookie或者webStorage中 window.token = data.Token; alert("登錄成功"); } else { alert("登錄失敗:" + data.Message); } }, error: function () { alert("程序錯誤"); } }) return false; })
7、前端調用api獲取數據
//get $("#btn_get").click(function () { $.ajax({ url: '/api/Users/getData/1', type: "get", headers: { "auth": window.token },//通過請求頭來發送token success: function (res) { console.log(res) if (res.code == 0) { alert("操作成功"); } else { alert("操作失敗:"+res.msg); } }, error: function (res) { alert("程序錯誤"); } }) return false; })
//over