周虎
摘? 要:JWT(JsonWebToken)認證作為一種服務器端無狀態(tài)驗證方式,在分布式開發(fā)中得到了廣泛的應用。但是,由于token信息的本身特點,支持的有效時間是固定的,當在token有效時間內用戶操作沒有完成,操作就會中斷,需要重新登錄驗證。本文通過對比傳統(tǒng)Cookie/Session身份驗證機制在分布式開發(fā)中存在的不足,提出了一種基于JWT認證過程中動態(tài)刷新token的方法,有效地解決了分布式開發(fā)中會話共享問題,并通過在webApi開發(fā)中得到了具體的應用,表明了該方法的有效性和實用性。
關鍵詞:JWT;token;認證;webApi
中圖分類號:TP311.11? ? ?文獻標識碼:A
Research on a Refresh Mechanism of Authentication Token Based on JWT
ZHOU Hu
(Xuzhou Finance and Economics Branch,Jiangsu Union Technical Institute,Xuzhou 221008,China)
Abstract:JWT (JSON Web Token) authentication,as a server-side stateless authentication method,has been widely used in distributed development.However,due to the characteristics of token information itself,the supported valid time is fixed.When the user operation is not completed within the token valid time,the operation will be interrupted and the login verification needs to be re-registered.By comparing the traditional Cookie/Session authentication mechanism in distributed development of deficiencies,this paper proposes a method based on dynamic refresh token JWT certification process,solving effectively the problem of the sharing Session in distributed development.The application in the webApi development shows that the method is effective and practical.
Keywords:JWT;token;authentication;webApi
1? ?引言(Introduction)
目前,隨著Web應用技術的不斷發(fā)展,應用程序的規(guī)模不斷擴大,分布式應用開發(fā)逐漸成了主流趨勢。傳統(tǒng)的Web程序認證技術基于Session和cookie技術的弊端已經(jīng)逐步顯露出來,在多臺服務器之間如何實現(xiàn)會話共享,保持會話一致,即使實現(xiàn)了會話復制,隨著服務器數(shù)量的不斷增加,Session復制性能也會急劇下降[1],給服務器的性能帶來損失,它們已經(jīng)不能滿足現(xiàn)代Web應用程序的發(fā)展需要??蛻舳撕头掌鞫藭挿蛛x,保持服務器端無狀態(tài)提供服務,同時又要保證服務器端資源的安全性,為了克服這些不足,基于JWT認證技術得到了廣泛關注,其通過特定的算法生成用戶唯一的令牌token對象,然后在用戶數(shù)據(jù)請求過程中攜帶此token即可完成身份有效性校驗,一方面保證了前后端分離,同時保護用戶訪問安全[2]。它與Session機制最大的區(qū)別就是一個將用戶認證信息保存在服務器端,一個保存在客戶端,大大減輕了服務器端的存儲壓力,同時提供了跨域訪問和分布式服務器集群訪問的身份認證。
基于JWT的認證方式雖然給身份認證方式帶來了極大的方便,但是也存在一些弊端,當服務器端簽發(fā)token時,它包含了簽發(fā)時間和失效時間,當在有效時間內,如果用戶操作沒有完成,服務器端將要求客戶端重新登錄,一方面可能導致數(shù)據(jù)丟失,同時給用戶體驗造成了負面影響。所以針對這種情況,本文提出了一種基于客戶端異步刷新token方式,一方面延長了token的有效時間,同時改善了用戶體驗,并通過JWT結合.netCore中的WebApi技術證明了該方法的可行性。
2? ?JWT(Json Web Token)
JWT是一種基于Json格式Web token,定義了一個緊湊的自包含的方式在不同實體之間安全傳輸信息[3]。它是在Web環(huán)境下兩個實體之間傳輸數(shù)據(jù)的一項標準。實際上傳輸?shù)木褪且粋€字符串。token信息包含了三個部分:HEAD頭部,用來聲明token類型和加密的算法;PAYLOAD載荷部分,主要用于傳遞信息的載體,常用的有iss(簽發(fā)者)、iat(簽發(fā)時間)、exp(過期時間)、sub(面向的用戶)、aud(接收方);SIGNATURE部分,用于將Header和Payload編碼后的字符串拼接后再用HS256簽名算法(Header中alg指明的算法)加密,在加密的過程中還需加上secret(密鑰),最后得到簽名,具體結構如圖1所示。
對于JWT認證方式,首先由客戶端發(fā)起用戶登錄請求,在服務端進行用戶信息驗證,驗證成功后,將給客戶端簽發(fā)token,簽發(fā)成功后,客戶端將簽發(fā)的token保存到客戶端,在進行服務器資源訪問時,需要在請求頭中放置簽發(fā)的token,服務器端接收到客戶端發(fā)送的token時,對其進行驗證是否合法,是否在有效時間內,如果在有效時間內并且用戶身份合法,將返回服務器資源,具體流程如圖2所示。
基于JWT的認證方式,由于Json的通用性,所以JWT是可以進行跨語言支持,有了PAYLOAD部分,所以JWT可以在自身存儲一些其他業(yè)務邏輯所必要的非敏感信息。JWT構成非常簡單,字節(jié)占用很小,所以它是非常便于傳輸?shù)模⑶也辉诜斩吮4鏁捫畔?,更易于應用的擴展[4]。
3? token動態(tài)刷新功能的實現(xiàn)(Implementation of token dynamic refresh function)
當客戶端發(fā)出認證請求,服務端接收客戶端發(fā)送的用戶信息并驗證合法性,驗證通過后給客戶端返回頒發(fā)的token、頒發(fā)時間和失效時間,客戶端根據(jù)接收的信息,計算客戶端當前時間和token的頒發(fā)時間的時間偏差,將token、頒發(fā)時間、失效時間和時間偏差保存到瀏覽器的localstorage中??蛻舳嗽谶M行WebApi訪問時,客戶端從localstorage中取出信息計算當前時間加上時間偏差并和token的失效時間進行比較,如果距離失效時間不在限定時間范圍內(比如2分鐘),直接進行請求WebApi,否則,先進行異步請求登錄認證,然后在進行WebApi請求[5],具體流程如圖3所示。
當客戶端重新請求時,服務器端將重新頒發(fā)token,并將頒發(fā)時間、失效時間和客戶端的時間偏差值重新保存到客戶端的localstorage中,再次請求WebApi時將攜帶新的token。
為了驗證客戶端動態(tài)刷新token功能,本文采用JWT結合.netCore平臺中的WebApi技術,實現(xiàn)對客戶端訪問控制,主要實現(xiàn)兩個部分:服務端認證并簽發(fā)token和客戶端請求token。
3.1? ?服務端認證并簽發(fā)token
當客戶端發(fā)送請求用戶名和密碼進行驗證時,服務器端先驗證用戶的合法性,如果用戶合法,將給用戶頒發(fā)token,實現(xiàn)代碼如下:
if (validateUser(userInfo)//驗證用戶合法
{
long curTime=DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
long endTime=DateTimeOffset.UtcNow.AddMinutes(20).ToUnixTimeMilliseconds();
LoginInfo pUserLoginInfo=new LoginInfo() { Name=UserName,Password=PassWord,exp=endTime };
var token=new JwtBuilder()//簽發(fā)token
.WithAlgorithm(new HMACSHA256Algorithm())//指定算法
.WithSecret(m_Secret)//密鑰
.ExpirationTime(DateTime.UtcNow.AddMinutes(5))//過期時間
.AddClaim("issuser","xzcx")//頒發(fā)者
.AddClaim("audience",userInfo.Name)//接收者
.Build();
jwtResult=new JwtResult()
{
token=token,
statusCode="200",
message="success",
assTime=curTime,//簽發(fā)時間
endTime=endTime
};
return JsonConvert.SerializeObject(jwtResult);
}
當服務器端簽發(fā)token時,指定簽發(fā)時間和失效時間,在上面程序中,指定token失效時間為當前時間后20分鐘,并且所有時間格式按照Unix格式時間戳來保存。簽發(fā)token成功后將token和狀態(tài)碼,返回消息以及簽發(fā)時間和失效時間以JSON格式響應到客戶端[6]。
3.2? ?客戶端保存token并請求WebApi
當客戶端接收到服務端響應的token信息,將其保存到客戶端的localstorage中,實現(xiàn)代碼如下:
$.ajax({
url:'https://localhost:44337/api/service',
data:{UserName:username,PassWord:password},
success:function (data) {
var result=$.parseJSON(data);
localStorage.setItem("token",result.token);//保存token
localStorage.setItem("assTime",result.assTime);//保存頒發(fā)時間
localStorage.setItem("endTime",result.endTime);//保存失效時間
localStorage.setItem("offsetTime",new Date().getTime()-result.curTime);//保存客戶端和服務端時間差
}
})
當用戶請求WebApi時,將從localstorage中取出token信息,并加入請求head中,但是,在請求前需要判斷一下當前時間和token的失效時間差是否在設定時間內,如果在設定內,需要重新請求認證并保存新的token,然后再次訪問WebApi[7],實現(xiàn)代碼如下:
var token=localStorage.getItem("token");
var curTime=localStorage.getItem("curTime");
var offsetTime=localStorage.getItem("offsetTime");
var endTime=localStorage.getItem("endTime");
if ((parseInt(endTime)-(new Date().getTime()+parseInt(offsetTime))<120000)) {//如果時間差在2分鐘以內則重新請求認證
var promise=new Promise(function (resolve,reject) {
login()//重新登錄驗證
})
promise.then(visitApi(url));? ?//請求成功后再訪問WebApi
}
else {
visitApi(url);//如果時間差大于2分鐘直接訪問WebApi
}
在實現(xiàn)重新請求認證時,需要用到Promise對象,因為在重新請求認證和訪問WebApi時有先后順序,必須要等到服務端重新頒發(fā)token并且客戶端保存成功后再次攜帶新的token訪問WebApi,否則將訪問失敗。經(jīng)過測試發(fā)現(xiàn),客戶端動態(tài)刷新token方法在不影響用戶操作體驗的情況下動態(tài)延長token有效期限,有效地解決了token失效問題[8]。
4? ?結論(Conclusion)
本文通過對目前基于JWT認證機制下token失效問題進行了深入研究,為了更好保證在不影響用戶操作的前提下,動態(tài)延長token的有效期限,提出了一種基于客戶端在設定時間內動態(tài)刷新token的方法,并在.netCore平臺下的WebApi技術中得到了具體的驗證,該方法簡單有效地解決了token失效問題,同時大大減輕了服務器端的負擔,也為前后端分離提供有效地解決方案[9]。
參考文獻(References)
[1] 柳綱,張毅.服務端無狀態(tài)技術研究[J].電力信息與通信技術,2017(11):49-54.
[2] 陳宇收,饒宏博,王英明,等.基于JWT 的前后端分離程序設計研究[J].電腦編程技巧與維護,2019(09):11-12.
[3] 范展源,羅福強.JWT認證技術及其在Web中的應用[J].數(shù)字技術與應用,2016(02):114.
[4] 項武銘,鮑亮,俞少華.基于JWT的RESTful API角色權限驗證方案設計[J].現(xiàn)代計算機(專業(yè)版),2018(12):82-85.
[5] 黃偉民,陳可新.基于Token的物聯(lián)網(wǎng)云平臺系統(tǒng)身份認證機制研究[J].智庫時代,2018(42):195-196.
[6] 王威.物聯(lián)網(wǎng)的體系結構與相關技術[J].電子技術與軟程,2018(22):14-15.
[7] 王守昌.JWT從入門到精通[EB/OL].https://www.cnblogs.com/wangshouchang/p/9551748.html,2018-08-28.
[8] LIU Gang,HE Jing.Design of a high performance WEB cluster[J].Electric Power Information and Communication Technology,2017,15(3):95-100.
[9] Woo-Suk Park,Dong-Yeop Hwang.A TOTP-Based Two Factor Authentication Scheme for Hyperledger Fabric Blockchain[J].2018 Tenth International Conference on Ubiquitous and Future Networks(ICUFN),2018(05):78-81.
作者簡介:
周? 虎(1977-),男,碩士,講師.研究領域:應用程序設計.