今天修改項(xiàng)目的登陸認(rèn)證問(wèn)題赴精,之前用的shiro+freemarker雇初。后來(lái)項(xiàng)目改成了前后端分離戏罢,全部使用json進(jìn)行前后臺(tái)數(shù)據(jù)交互硝清,于是想做一個(gè)登錄認(rèn)證的功能辅斟,網(wǎng)上找了下資料,這里做下總結(jié)芦拿。
1. 使用token
- 前端把a(bǔ)ccount和password士飒,提交到服務(wù)端的登錄api查邢;
- 服務(wù)端驗(yàn)證正確后,生成一個(gè)token酵幕,并把token和userId扰藕,存在緩存里(推薦redis數(shù)據(jù)庫(kù)),然后把token返回給前端芳撒;
- 前端每次的請(qǐng)求頭中帶token邓深。
這里要引入下JWT。
1.1 JWT基本概念
Json web token (JWT), 是為了在網(wǎng)絡(luò)應(yīng)用環(huán)境間傳遞聲明而執(zhí)行的一種基于JSON的開放標(biāo)準(zhǔn)((RFC 7519).該token被設(shè)計(jì)為緊湊且安全的笔刹,特別適用于分布式站點(diǎn)的單點(diǎn)登錄(SSO)場(chǎng)景芥备。JWT的聲明一般被用來(lái)在身份提供者和服務(wù)提供者間傳遞被認(rèn)證的用戶身份信息,以便于從資源服務(wù)器獲取資源徘熔,也可以增加一些額外的其它業(yè)務(wù)邏輯所必須的聲明信息门躯,該token也可直接被用于認(rèn)證,也可被加密酷师。
1.1.1 組成部分
由三部分構(gòu)成:
header.payload.signature
header(頭部)
{
"typ": "JWT", // 聲明這是JWT
"alg": "HS256" // 聲明簽名的加密方式
}
將這部分信息進(jìn)行BASE64編碼后讶凉,就是jwt.頭部
payload(載荷)
- 標(biāo)準(zhǔn)中注冊(cè)的聲明
- 公共的聲明
- 私有的聲明
- ?
{
"iss": "John Wu JWT",
"iat": 1441593502,
"exp": 1441594722,
"aud": "www.example.com",
"sub": "jrocket@example.com",
"from_user": "B",
"target_user": "A"
}
- iss: jwt簽發(fā)者
- sub: jwt所面向的用戶
- aud: 接收jwt的一方
- exp: jwt的過(guò)期時(shí)間,這個(gè)過(guò)期時(shí)間必須要大于簽發(fā)時(shí)間
- nbf: 定義在什么時(shí)間之前山孔,該jwt都是不可用的.
- iat: jwt的簽發(fā)時(shí)間
- jti: jwt的唯一身份標(biāo)識(shí)懂讯,主要用來(lái)作為一次性token,從而回避重放攻擊。
公共的聲明
公共的聲明可以添加任何的信息台颠,一般添加用戶的相關(guān)信息或其他業(yè)務(wù)需要的必要信息.但不建議添加敏感信息褐望,因?yàn)樵摬糠衷诳蛻舳丝山饷?私有的聲明
私有聲明是提供者和消費(fèi)者所共同定義的聲明,一般不建議存放敏感信息串前,因?yàn)閎ase64是對(duì)稱解密的瘫里,意味著該部分信息可以歸類為明文信息。
自定義一個(gè)payload
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
將其進(jìn)行BASE64編碼后就是JWT的載荷部分
signature(簽名)
簽名是header.payload
加鹽secret
SHA256加密后生成的編碼荡碾,即頭部的BASE64編碼和載荷的BASE64編碼由句號(hào).相連后谨读,加上服務(wù)器的密鑰,再由頭部中定義的算法(一般是SHA256)加密生成的編碼
1.2 驗(yàn)證過(guò)程
客戶端向服務(wù)器發(fā)起請(qǐng)求后坛吁,服務(wù)端驗(yàn)證通過(guò)后生成jwt字符串返回給客戶端劳殖,客戶端在每次請(qǐng)求的時(shí)候在頭部加上Authorization,服務(wù)器接收請(qǐng)求后獲取拨脉,解析頭部的JWT字符串哆姻,會(huì)根據(jù)頭部和載荷中的字符串,加上服務(wù)器本地儲(chǔ)存的密鑰進(jìn)行SHA256加密計(jì)算玫膀,計(jì)算出的字符串如果跟請(qǐng)求中的JWT的簽名一致矛缨,則認(rèn)為認(rèn)證通過(guò)。
如果頭部和載荷中的任一字符改動(dòng),都會(huì)驗(yàn)證失敗劳景。
2. 使用cookie
- client發(fā)送username和password到server誉简;
- server驗(yàn)證成功后, 寫cookie到client盟广,然后返回ok的json,其中cookie的key要存儲(chǔ)在redis中瓮钥,value就是用戶信息筋量,并且要設(shè)置key的超時(shí)時(shí)間,如:60分鐘碉熄;
- client收到ok后桨武,進(jìn)行相應(yīng)的業(yè)務(wù)操作,以后每次請(qǐng)求server都會(huì)自動(dòng)帶上cookie锈津;
- server端的filter(用filter來(lái)實(shí)現(xiàn))中會(huì)每次驗(yàn)證傳過(guò)來(lái)的cookie的key在redis中是否存在呀酸, 有就代表登錄成功過(guò)可以操作,沒(méi)有就返回錯(cuò)誤標(biāo)識(shí)琼梆。注意: 在登錄成功后性誉,每次調(diào)用服務(wù)器接口時(shí)候, 都要為redis的key進(jìn)行續(xù)期茎杂,如60分鐘错览;
- 當(dāng)redis的key超過(guò)60分鐘,自己會(huì)刪除這個(gè)key煌往,那么再次請(qǐng)求server時(shí)倾哺,就會(huì)收到需要登錄的返回值;
- 當(dāng)用戶主動(dòng)退出系統(tǒng)的時(shí)候刽脖,也要在server中刪除redis的key羞海。