該文章轉(zhuǎn)載自https://juejin.cn/post/6844904034181070861
原作者ID為:秋天不落葉
原作者發(fā)表時(shí)間為:2019年12月29日
以便更好閱讀內(nèi)容細(xì)節(jié)經(jīng)過處理
什么是認(rèn)證(Authentication)
- 通俗地講就是驗(yàn)證當(dāng)前用戶的身份影兽,證明 “你是你自己”(比如:每天上下班需要通過指紋打卡,當(dāng)你的指紋和系統(tǒng)里錄入的指紋相匹配時(shí)莱革,則打卡成功)
- 互聯(lián)網(wǎng)中的認(rèn)證:
用戶名密碼登錄
郵箱發(fā)送登錄鏈接
手機(jī)號(hào)接收驗(yàn)證碼
只要能輸入正確的郵箱鏈接/驗(yàn)證碼峻堰,就可通過認(rèn)證
什么是授權(quán)(Authorization)
- 用戶授予第三方應(yīng)用訪問該用戶某些資源的權(quán)限
你在安裝使用手機(jī)APP時(shí) 會(huì)詢問是否允許授予權(quán)限(訪問相冊(cè)讹开、地理位置等權(quán)限)
你在使用微信小程序登錄時(shí)會(huì)詢問是否允許授予權(quán)限(獲取昵稱、頭像捐名、地區(qū)旦万、性別等個(gè)人信息)
實(shí)現(xiàn)授權(quán)的方式有:cookie、session镶蹋、token成艘、OAuth
什么是憑證(Credentials)
- 實(shí)現(xiàn)認(rèn)證和授權(quán)的前提是需要一種媒介(證書) 來標(biāo)記訪問者的身份
在戰(zhàn)國時(shí)期,商鞅變法發(fā)明了照身帖贺归。照身帖是官府發(fā)放的一塊打磨光滑細(xì)密的竹板淆两,上面刻有持有人的頭像和籍貫信息。若沒有的話會(huì)被認(rèn)為是黑戶拂酣,或者間諜之類的秋冰。
在現(xiàn)實(shí)生活中,每個(gè)人都會(huì)有一張專屬的居民身份證是用于證明持有人身份的一種法定證件婶熬,通過身份證剑勾,我們可以辦理手機(jī)卡/銀行卡/個(gè)人貸款/交通出行等等,這就是憑證
在互聯(lián)網(wǎng)應(yīng)用中尸诽,一般網(wǎng)站(如掘金)會(huì)有兩種模式甥材,游客模式和登錄模式。游客模式下性含,可以正常瀏覽網(wǎng)站上面的文章洲赵,但如果想要點(diǎn)贊/收藏/分享文章,就需要登錄或者注冊(cè)賬號(hào)商蕴。當(dāng)用戶登錄成功后叠萍,服務(wù)器會(huì)給該用戶使用的瀏覽器頒發(fā)一個(gè)令牌(token),這個(gè)令牌用來表明用戶的身份绪商,每次瀏覽器發(fā)送請(qǐng)求時(shí)都會(huì)帶上這個(gè)令牌苛谷,就可以使用游客模式下無法使用的功能
什么是 Cookie
HTTP 是無狀態(tài)的協(xié)議(對(duì)于事務(wù)處理沒有記憶能力,每次客戶端和服務(wù)端會(huì)話完成時(shí)格郁,服務(wù)端不會(huì)保存任何會(huì)話信息):每個(gè)請(qǐng)求都是完全獨(dú)立的腹殿,服務(wù)端無法確認(rèn)當(dāng)前訪問者的身份信息,無法分辨上一次的請(qǐng)求發(fā)送者和這一次的發(fā)送者是不是同一個(gè)人例书。所以服務(wù)器與瀏覽器為了進(jìn)行會(huì)話跟蹤(知道是誰在訪問我)锣尉,就必須主動(dòng)的去維護(hù)一個(gè)狀態(tài),這個(gè)狀態(tài)用于告知服務(wù)端前后兩個(gè)請(qǐng)求是否來自同一瀏覽器决采。而這個(gè)狀態(tài)需要通過 cookie 或者 session 去實(shí)現(xiàn)
cookie 存儲(chǔ)在客戶端: cookie 是服務(wù)器發(fā)送到用戶瀏覽器并保存在本地的一小塊數(shù)據(jù)自沧,它會(huì)在瀏覽器下次向同一服務(wù)器再發(fā)起請(qǐng)求時(shí)被攜帶并發(fā)送到服務(wù)器上
cookie 是不可跨域的: 每個(gè) cookie 都會(huì)綁定單一的域名,無法在別的域名下獲取使用树瞭,但一級(jí)域名和二級(jí)域名之間允許共享使用(靠的是 domain)
cookie的屬性
- name=value 【鍵值對(duì)拇厢,設(shè)置 Cookie 的名稱及相對(duì)應(yīng)的值爱谁,兩者都必須為字符串類型,如果值為 Unicode 字符孝偎,需要為字符編碼访敌。如果值為二進(jìn)制數(shù)據(jù),需要使用 BASE64 編碼】
- domain 【指定 cookie 所屬域名邪媳,默認(rèn)是當(dāng)前域名】
- path 【指定 cookie 在哪個(gè)路徑(路由)下生效捐顷,默認(rèn)是 '/'。如果設(shè)置為 /abc雨效,則只有 /abc 下的路由可以訪問到該 cookie,如:/abc/read】
- maxAge 【cookie 失效的時(shí)間废赞,單位秒徽龟。如果為整數(shù),則該 cookie 在 maxAge 秒后失效唉地。如果為負(fù)數(shù)据悔,該 cookie 為臨時(shí) cookie ,關(guān)閉瀏覽器即失效耘沼,瀏覽器也不會(huì)以任何形式保存該 cookie 极颓。如果為 0,表示刪除該 cookie 群嗤。默認(rèn)為 -1】
- expires 【過期時(shí)間菠隆,在設(shè)置的某個(gè)時(shí)間點(diǎn)后該 cookie 就會(huì)失效。一般瀏覽器的 cookie 都是默認(rèn)儲(chǔ)存的狂秘,當(dāng)關(guān)閉瀏覽器結(jié)束這個(gè)會(huì)話的時(shí)候骇径,這個(gè) cookie 也就會(huì)被刪除】
- secure 【該 cookie 是否僅被使用安全協(xié)議傳輸。安全協(xié)議有 HTTPS者春,SSL等破衔,在網(wǎng)絡(luò)上傳輸數(shù)據(jù)之前先將數(shù)據(jù)加密。默認(rèn)為false钱烟。當(dāng) secure 值為 true 時(shí)晰筛,cookie 在 HTTP 中是無效,在 HTTPS 中才有效】
- httpOnly 【如果給某個(gè) cookie 設(shè)置了 httpOnly 屬性拴袭,則無法通過 JS 腳本讀取到該 cookie 的信息读第,但還是能通過瀏覽器的Application功能手動(dòng)修改 cookie】
什么是 Session
- session 是另一種記錄服務(wù)器和客戶端會(huì)話狀態(tài)的機(jī)制
- session 是基于 cookie 實(shí)現(xiàn)的,session 存儲(chǔ)在服務(wù)器端稻扬,sessionId 會(huì)被存儲(chǔ)到客戶端的cookie 中
- Session 認(rèn)證流程:
- 用戶第一次請(qǐng)求服務(wù)器的時(shí)候卦方,服務(wù)器根據(jù)用戶提交的相關(guān)信息,創(chuàng)建對(duì)應(yīng)的 Session
- 請(qǐng)求返回時(shí)將此 Session 的唯一標(biāo)識(shí)信息 SessionID 返回給瀏覽器
- 瀏覽器接收到服務(wù)器返回的 SessionID 信息后泰佳,會(huì)將此信息存入到 Cookie 中盼砍,同時(shí) Cookie 記錄此 SessionID 屬于哪個(gè)域名
- 當(dāng)用戶第二次訪問服務(wù)器的時(shí)候尘吗,請(qǐng)求會(huì)自動(dòng)判斷此域名下是否存在 Cookie 信息,如果存在自動(dòng)將 Cookie 信息也發(fā)送給服務(wù)端浇坐,服務(wù)端會(huì)從 Cookie 中獲取 SessionID睬捶,再根據(jù) SessionID 查找對(duì)應(yīng)的 Session 信息,如果沒有找到說明用戶沒有登錄或者登錄失效近刘,如果找到 Session 證明用戶已經(jīng)登錄可執(zhí)行后面操作擒贸。
根據(jù)以上流程可知,SessionID 是連接 Cookie 和 Session 的一道橋梁觉渴,大部分系統(tǒng)也是根據(jù)此原理來驗(yàn)證用戶登錄狀態(tài)介劫。
Cookie 和 Session 的區(qū)別
- 安全性: Session 比 Cookie 安全,Session 是存儲(chǔ)在服務(wù)器端的案淋,Cookie 是存儲(chǔ)在客戶端的
- 存取值的類型不同:Cookie 只支持存字符串?dāng)?shù)據(jù)座韵,想要設(shè)置其他類型的數(shù)據(jù),需要將其轉(zhuǎn)換成字符串踢京,Session 可以存任意數(shù)據(jù)類型
- 有效期不同: Cookie 可設(shè)置為長時(shí)間保持誉碴,比如我們經(jīng)常使用的默認(rèn)登錄功能,Session 一般失效時(shí)間較短瓣距,客戶端關(guān)閉(默認(rèn)情況下)或者 Session 超時(shí)都會(huì)失效
- 存儲(chǔ)大小不同: 單個(gè) Cookie 保存的數(shù)據(jù)不能超過 4K黔帕,Session 可存儲(chǔ)數(shù)據(jù)遠(yuǎn)高于 Cookie,但是當(dāng)訪問量過多蹈丸,會(huì)占用過多的服務(wù)器資源
什么是 Token(令牌)
Access Token是指訪問資源接口(API)時(shí)所需要的資源憑證
Token的組成由:uid(用戶唯一的身份標(biāo)識(shí))成黄、time(當(dāng)前時(shí)間的時(shí)間戳)、sign(簽名白华,token 的前幾位以哈希算法壓縮成的一定長度的十六進(jìn)制字符串)
Token的特點(diǎn):服務(wù)端無狀態(tài)化慨默、可擴(kuò)展性好、支持移動(dòng)端設(shè)備弧腥、支持跨程序調(diào)用厦取、安全
- Token的身份驗(yàn)證流程為
- 客戶端使用用戶名跟密碼請(qǐng)求登錄
- 服務(wù)端收到請(qǐng)求,去驗(yàn)證用戶名與密碼
- 驗(yàn)證成功后管搪,服務(wù)端會(huì)簽發(fā)一個(gè) Access Token 并把這個(gè) Access Token 發(fā)送給客戶端
- 客戶端收到 Access Token 以后虾攻,會(huì)把它存儲(chǔ)起來,比如放在 Cookie 里或者 本地文件 里
- 客戶端每次向服務(wù)端請(qǐng)求資源的時(shí)候需要帶著服務(wù)端簽發(fā)的 Access Token
- 服務(wù)端收到請(qǐng)求更鲁,然后去驗(yàn)證客戶端請(qǐng)求里面帶著的 Access Token 霎箍,如果驗(yàn)證成功,就向客戶端返回請(qǐng)求的數(shù)據(jù)
- Access Token的特點(diǎn)
- 每一次請(qǐng)求都需要攜帶 Access Token澡为,需要把 Access Token 放到 HTTP 的 Header 里
- 基于 Access Token 的用戶認(rèn)證是一種服務(wù)端無狀態(tài)的認(rèn)證方式漂坏,服務(wù)端不用存放 Access Token 數(shù)據(jù)。用解析 Access Token 的計(jì)算時(shí)間換取 Session 的存儲(chǔ)空間,從而減輕服務(wù)器的存儲(chǔ)壓力顶别,減少服務(wù)器頻繁查詢數(shù)據(jù)庫的計(jì)算壓力
- Access Token 完全由應(yīng)用管理谷徙,所以它可以避開同源策略
什么是Refresh Token
Refresh Token是另一種Token的實(shí)現(xiàn)形式,是專門用于刷新 Access Token 的 Token驯绎。如果沒有 Refresh Token每次 Access Token 刷新都要用戶輸入用戶名與密碼完慧。有了 Refresh Token,可以減少這個(gè)麻煩剩失,客戶端直接用 Refresh Token 去更新 Access Token屈尼,無需用戶進(jìn)行額外的操作
- Refresh Token的特點(diǎn)
- Access Token 的有效期比較短,當(dāng) Access Token 由于過期而失效時(shí)拴孤,使用 Refresh Token 就可以獲取到新的 Token脾歧,如果 Refresh Token 也失效了,用戶就只能重新登錄
- Refresh Token 及過期時(shí)間是存儲(chǔ)在服務(wù)器的數(shù)據(jù)庫中演熟,只有在申請(qǐng)新的 Access Token 時(shí)才會(huì)驗(yàn)證涨椒,不會(huì)對(duì)業(yè)務(wù)接口響應(yīng)時(shí)間造成影響,也不需要向 Session 一樣一直保持在內(nèi)存中以應(yīng)對(duì)大量的請(qǐng)求
Token 和 Session 的區(qū)別
- Session 是一種記錄服務(wù)器和客戶端會(huì)話狀態(tài)的機(jī)制绽媒,使服務(wù)端有狀態(tài)化,可以記錄會(huì)話信息免猾。而 Token 是令牌是辕,訪問資源接口(API)時(shí)所需要的資源憑證。Token 使服務(wù)端無狀態(tài)化猎提,不會(huì)存儲(chǔ)會(huì)話信息
- Session 和 Token 并不矛盾获三,作為身份認(rèn)證 Token 安全性比 Session 好,因?yàn)槊恳粋€(gè)請(qǐng)求都有簽名還能防止監(jiān)聽以及重放攻擊锨苏,而 Session 就必須依賴鏈路層來保障通訊安全了疙教。如果你需要實(shí)現(xiàn)有狀態(tài)的會(huì)話,仍然可以增加 Session 來在服務(wù)器端保存一些狀態(tài)
- 所謂 Session 認(rèn)證只是簡(jiǎn)單的把 User 信息存儲(chǔ)到 Session 里伞租,因?yàn)?SessionID 的不可預(yù)測(cè)性贞谓,暫且認(rèn)為是安全的。而 Token 葵诈,如果指的是 OAuth Token 或類似的機(jī)制的話裸弦,提供的是 認(rèn)證 和 授權(quán) ,認(rèn)證是針對(duì)用戶作喘,授權(quán)是針對(duì) App 理疙。其目的是讓某 App 有權(quán)利訪問某用戶的信息。這里的 Token 是唯一的泞坦。不可以轉(zhuǎn)移到其它 App上窖贤,也不可以轉(zhuǎn)到其它用戶上。Session 只提供一種簡(jiǎn)單的認(rèn)證,即只要有此 SessionID 赃梧,即認(rèn)為有此 User 的全部權(quán)利滤蝠。是需要嚴(yán)格保密的,這個(gè)數(shù)據(jù)應(yīng)該只保存在站方槽奕,不應(yīng)該共享給其它網(wǎng)站或者第三方 App几睛。所以簡(jiǎn)單來說:如果你的用戶數(shù)據(jù)可能需要和第三方共享,或者允許第三方調(diào)用 API 接口粤攒,用 Token
什么是 JWT
JSON Web Token(簡(jiǎn)稱 JWT)是一種認(rèn)證授權(quán)機(jī)制是目前最流行的跨域認(rèn)證解決方案所森,JWT 是為了在網(wǎng)絡(luò)應(yīng)用環(huán)境間傳遞聲明而執(zhí)行的一種基于 JSON 的開放標(biāo)準(zhǔn)。JWT 的聲明一般被用來在身份提供者和服務(wù)提供者間傳遞被認(rèn)證的用戶身份信息夯接,以便于從資源服務(wù)器獲取資源焕济。比如用在用戶登錄上,因?yàn)镴WT 可以使用 HMAC 算法或者是 RSA 的公/私秘鑰進(jìn)行簽名盔几。所以經(jīng)過JWT加密后傳遞的信息是可信的
原作者推薦JWT教程老師:阮一峰
鏈接:http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html
- JWT認(rèn)證流程
- 用戶輸入用戶名/密碼登錄晴弃,服務(wù)端認(rèn)證成功后,會(huì)返回給客戶端一個(gè) JWT
- 客戶端將 Access Token 保存到本地(通常使用 本地文件逊拍,也可以使用 cookie)
- 當(dāng)用戶希望訪問一個(gè)受保護(hù)的路由或者資源的時(shí)候上鞠,需要請(qǐng)求頭的 Authorization 字段中使用Bearer 模式添加 JWT:Authorization: Bearer <Token>
- JWT的特點(diǎn)
- 服務(wù)端的保護(hù)路由將會(huì)檢查請(qǐng)求頭 Authorization 中的 JWT 信息,如果合法芯丧,則允許用戶的行為
- JWT 是自包含的(內(nèi)部包含了一些會(huì)話信息)芍阎,因此減少了服務(wù)器需要查詢數(shù)據(jù)庫的需要
- JWT 并不使用 Cookie 的,所以可以使用任何域名提供的 API 服務(wù)而不需要擔(dān)心跨域資源共享問題(CORS)
- 用戶的狀態(tài)不存儲(chǔ)在服務(wù)端的內(nèi)存中缨恒,所以這是一種無狀態(tài)的認(rèn)證機(jī)制
- JWT的使用方式
- 添加到header中:
GET /calendar/v1/events
Host: api.example.com
Authorization: Bearer <token> - 添加到post請(qǐng)求中:requests.post(url,headers=header,data=tokenData)
- 添加到鏈接中:https:url/user?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
- 添加到header中:
Token 和 JWT 的聯(lián)系和區(qū)別
- 聯(lián)系
- 都是訪問資源的令牌
- 都可以記錄用戶的信息
- 都是使服務(wù)端無狀態(tài)化
- 都是只有驗(yàn)證成功后谴咸,客戶端才能訪問服務(wù)端上受保護(hù)的資源
- 區(qū)別
- Token:服務(wù)端驗(yàn)證客戶端發(fā)送過來的 Token 時(shí),還需要查詢數(shù)據(jù)庫獲取用戶信息骗露,然后驗(yàn)證 Token 是否有效
- JWT: 將 Token 和 Payload 加密后存儲(chǔ)于客戶端岭佳,服務(wù)端只需要使用密鑰解密進(jìn)行校驗(yàn)(校驗(yàn)也是 JWT 自己實(shí)現(xiàn)的)即可,不需要查詢或者減少查詢數(shù)據(jù)庫萧锉,因?yàn)?JWT 自包含了用戶信息和加密的數(shù)據(jù)
常見的前后端鑒權(quán)方式
- Session-Cookie
- Token 驗(yàn)證(包括 JWT珊随,SSO)
- OAuth2.0(開放授權(quán))
常見的哈希加密算法
哈希算法又稱散列算法、散列函數(shù)驹暑、哈希函數(shù)玫恳,是一種從任何一種數(shù)據(jù)中創(chuàng)建小的數(shù)字“指紋”的方法。哈希算法將數(shù)據(jù)重新打亂混合优俘,重新創(chuàng)建一個(gè)哈希值京办,哈希算法主要用來保障數(shù)據(jù)真實(shí)性(即完整性),即發(fā)信人將原始消息和哈希值一起發(fā)送帆焕,收信人通過相同的哈希函數(shù)來校驗(yàn)原始數(shù)據(jù)是否真實(shí)
- 哈希算法的特點(diǎn)
- 正向快速:原始數(shù)據(jù)可以快速計(jì)算出哈希值
- 逆向困難:通過哈希值基本不可能推導(dǎo)出原始數(shù)據(jù)
- 輸入敏感:原始數(shù)據(jù)只要有一點(diǎn)變動(dòng)惭婿,得到的哈希值差別很大
- 沖突避免:很難找到不同的原始數(shù)據(jù)得到相同的哈希值不恭,宇宙中原子數(shù)大約在 10 的 60 次方到 80 次方之間,所以 2 的 256 次方有足夠的空間容納所有的可能财饥,算法好的情況下沖突碰撞的概率很低
常見問題
- 使用 Cookie 時(shí)需要考慮的問題
- 存儲(chǔ)在客戶端换吧,容易被客戶端篡改,使用前需要驗(yàn)證合法性
- 不要存儲(chǔ)敏感數(shù)據(jù)钥星,比如用戶密碼沾瓦,賬戶余額
- 使用 httpOnly 可以在一定程度上提高安全性
- 盡量減少 Cookie 的體積,能存儲(chǔ)的數(shù)據(jù)量不能超過 4kb
- 設(shè)置正確的 domain 和 path谦炒,減少數(shù)據(jù)傳輸
- Cookie 無法跨域
- 一個(gè)瀏覽器針對(duì)一個(gè)網(wǎng)站最多存 20 個(gè)Cookie贯莺,瀏覽器一般只允許存放 300 個(gè)Cookie
- 移動(dòng)端對(duì) Cookie 的支持不是很好,而 Session 需要基于 Cookie 實(shí)現(xiàn)宁改,所以移動(dòng)端常用的是 Token
- 使用 Session 時(shí)需要考慮的問題
- Session 存儲(chǔ)在服務(wù)器里面缕探,當(dāng)用戶同時(shí)在線量比較多時(shí),這些 Session 會(huì)占據(jù)較多的內(nèi)存还蹲,需要在服務(wù)端定期的去清理過期的 Session
- 當(dāng)網(wǎng)站采用集群部署的時(shí)候爹耗,會(huì)遇到多臺(tái) web 服務(wù)器之間如何做 Session 共享的問題。因?yàn)?Session 是由單個(gè)服務(wù)器創(chuàng)建的谜喊,但是處理用戶請(qǐng)求的服務(wù)器不一定是那個(gè)創(chuàng)建 Session 的服務(wù)器潭兽,那么該服務(wù)器就無法拿到之前已經(jīng)放入到 Session 中的登錄憑證之類的信息
- 當(dāng)多個(gè)應(yīng)用要共享 Session 時(shí),除了以上問題斗遏,還會(huì)遇到跨域問題讼溺,因?yàn)椴煌膽?yīng)用可能部署的主機(jī)不一樣,需要在各個(gè)應(yīng)用做好 Cookie 跨域的處理
- SessionId 是存儲(chǔ)在 cookie 中的最易,假如瀏覽器禁止 Cookie 或不支持 Cookie 怎么辦? 一般會(huì)把 SessionId 跟在 url 參數(shù)后面即重寫 url炫狱,所以 Session 不一定非得需要靠 Cookie 實(shí)現(xiàn)
- 關(guān)閉瀏覽器并不會(huì)導(dǎo)致Session丟失藻懒,除非通知服務(wù)器刪除Session,但當(dāng)使用會(huì)話 Cookie 來保存 SessionId時(shí)视译,關(guān)閉瀏覽器后雖然這個(gè) SessionId 消失并且再次連接服務(wù)器時(shí)也就無法找到原來的 Session嬉荆,但并不意味著服務(wù)器上的Session就會(huì)一并刪除,這一意味著迫使服務(wù)器要為 Session 設(shè)置了一個(gè)失效時(shí)間酷含,否則已經(jīng)過期的無效的Session會(huì)越積越多
- 使用 Token 時(shí)需要考慮的問題
- 如果用數(shù)據(jù)庫來存儲(chǔ) Token 會(huì)導(dǎo)致查詢時(shí)間太長鄙早,可以選擇放在內(nèi)存當(dāng)中。比如 redis 很適合對(duì) Token 查詢的需求
- Token 完全由應(yīng)用管理椅亚,所以它可以避開同源策略
- Token 可以避免 CSRF 攻擊(因?yàn)椴恍枰?cookie )
- 使用 JWT 時(shí)需要考慮的問題
- JWT 并不依賴 Cookie 限番,所以可以使用任何域名提供你的 API 服務(wù)而不需要擔(dān)心跨域資源共享問題(CORS)
- JWT 默認(rèn)是不加密,但也是可以加密的呀舔。生成原始 Token 以后弥虐,可以用密鑰再加密一次
- JWT 不加密的情況下,不能將秘密數(shù)據(jù)寫入 JWT
- JWT 不僅可以用于認(rèn)證,也可以用于交換信息霜瘪。有效使用 JWT珠插,可以降低服務(wù)器查詢數(shù)據(jù)庫的次數(shù)
- JWT 最大的優(yōu)勢(shì)是服務(wù)器不再需要存儲(chǔ) Session,使得服務(wù)器認(rèn)證鑒權(quán)業(yè)務(wù)可以方便擴(kuò)展颖对。但這也是 JWT 最大的缺點(diǎn):由于服務(wù)器不需要存儲(chǔ) Session 狀態(tài)捻撑,因此使用過程中無法廢棄某個(gè) Token 或者更改 Token 的權(quán)限。也就是說一旦 JWT 簽發(fā)了缤底,到期之前就會(huì)始終有效顾患,除非服務(wù)器部署額外的邏輯
- JWT 本身包含了認(rèn)證信息,一旦泄露训堆,任何人都可以獲得該令牌的所有權(quán)限描验。為了減少盜用,JWT的有效期應(yīng)該設(shè)置得比較短坑鱼。對(duì)于一些比較重要的權(quán)限膘流,使用時(shí)應(yīng)該再次對(duì)用戶進(jìn)行認(rèn)證
- JWT 適合一次性的命令認(rèn)證,頒發(fā)一個(gè)有效期極短的 JWT鲁沥,即使暴露了危險(xiǎn)也很小呼股,由于每次操作都會(huì)生成新的 JWT,因此也沒必要保存 JWT画恰,真正實(shí)現(xiàn)無狀態(tài)
- 為了減少盜用彭谁,JWT 不應(yīng)該使用 HTTP 協(xié)議明碼傳輸,要使用 HTTPS 協(xié)議傳輸
- 使用加密算法時(shí)需要考慮的問題
- 絕不要以明文存儲(chǔ)密碼
- 永遠(yuǎn)使用 哈希算法 來處理密碼允扇,絕不要使用 Base64 或其他編碼方式來存儲(chǔ)密碼缠局,這和以明文存儲(chǔ)密碼是一樣的,使用哈希考润,而不要使用編碼狭园。編碼以及加密,都是雙向的過程糊治,而密碼是保密的唱矛,應(yīng)該只被它的所有者知道, 這個(gè)過程必須是單向的井辜。哈希正是用于做這個(gè)的绎谦,從來沒有解哈希這種說法, 但是編碼就存在解碼粥脚,加密就存在解密
- 絕不要使用弱哈锨猿Γ或已被破解的哈希算法,像 MD5 或 SHA1 刷允,只使用強(qiáng)密碼哈希算法
- 絕不要以明文形式顯示或發(fā)送密碼铭拧,即使是對(duì)密碼的所有者也應(yīng)該這樣赃蛛。如果需要 “忘記密碼” 的功能,可以隨機(jī)生成一個(gè)新的 一次性的(這點(diǎn)很重要)密碼搀菩,然后把這個(gè)密碼發(fā)送給用戶
其他附帶問題
- 分布式架構(gòu)下 Session 共享方案
- Session 復(fù)制呕臂,任何一個(gè)服務(wù)器上的 Session 發(fā)生改變(增刪改),該節(jié)點(diǎn)會(huì)把這個(gè) Session 的所有內(nèi)容序列化肪跋,然后廣播給所有其它節(jié)點(diǎn)歧蒋,不管其他服務(wù)器需不需要 Session ,以此來保證 Session 同步
特點(diǎn):可容錯(cuò)州既,各個(gè)服務(wù)器間 Session 能夠?qū)崟r(shí)響應(yīng)
缺點(diǎn):會(huì)對(duì)網(wǎng)絡(luò)負(fù)荷造成一定壓力谜洽,如果 Session 量大的話可能會(huì)造成網(wǎng)絡(luò)堵塞,拖慢服務(wù)器性能 - 粘性 Session /IP 綁定策略吴叶,采用 Ngnix 中的 ip_hash 機(jī)制阐虚,將某個(gè) ip的所有請(qǐng)求都定向到同一臺(tái)服務(wù)器上,即將用戶與服務(wù)器綁定蚌卤。 用戶第一次請(qǐng)求時(shí)实束,負(fù)載均衡器將用戶的請(qǐng)求轉(zhuǎn)發(fā)到了 A 服務(wù)器上,如果負(fù)載均衡器設(shè)置了粘性 Session 的話逊彭,那么用戶以后的每次請(qǐng)求都會(huì)轉(zhuǎn)發(fā)到 A 服務(wù)器上咸灿,相當(dāng)于把用戶和 A 服務(wù)器粘到了一塊,這就是粘性 Session 機(jī)制
優(yōu)點(diǎn):簡(jiǎn)單侮叮,不需要對(duì) Session 做任何處理
缺點(diǎn):缺乏容錯(cuò)性避矢,如果當(dāng)前訪問的服務(wù)器發(fā)生故障,用戶被轉(zhuǎn)移到第二個(gè)服務(wù)器上時(shí)囊榜,他的 Session 信息都將失效
適用場(chǎng)景:發(fā)生故障對(duì)客戶產(chǎn)生的影響較猩笮亍;服務(wù)器發(fā)生故障是低概率事件
實(shí)現(xiàn)方式:以 Nginx 為例卸勺,在 upstream 模塊配置 ip_hash 屬性即可實(shí)現(xiàn)粘性 Session - Session共享(常用)歹嘹,使用分布式緩存方案比如 Memcached 、Redis 來緩存 session孔庭,但是要求 Memcached 或 Redis 必須是集群,把 Session 放到 Redis 中存儲(chǔ)材蛛,雖然架構(gòu)上變得復(fù)雜圆到,并且需要多訪問一次 Redis,但可以帶來Session 共享卑吭、可以水平擴(kuò)展(增加 Redis 服務(wù)器)芽淡、服務(wù)器重啟 Session 不丟失(不過也要注意 Session 在 Redis 中的刷新/失效機(jī)制)、不僅可以跨服務(wù)器 Session 共享豆赏,甚至可以跨平臺(tái)(例如網(wǎng)頁端和 APP 端)
- Session持久化苇瓣,將 Session 存儲(chǔ)到數(shù)據(jù)庫中,保證 Session 的持久化
優(yōu)點(diǎn):服務(wù)器出現(xiàn)問題蛆橡,Session 不會(huì)丟失
缺點(diǎn):如果網(wǎng)站的訪問量很大鳄橘,把 Session 存儲(chǔ)到數(shù)據(jù)庫中,會(huì)對(duì)數(shù)據(jù)庫造成很大壓力茧痒,還需要增加額外的開銷維護(hù)數(shù)據(jù)庫
- Session 復(fù)制呕臂,任何一個(gè)服務(wù)器上的 Session 發(fā)生改變(增刪改),該節(jié)點(diǎn)會(huì)把這個(gè) Session 的所有內(nèi)容序列化肪跋,然后廣播給所有其它節(jié)點(diǎn)歧蒋,不管其他服務(wù)器需不需要 Session ,以此來保證 Session 同步