cookie,token驗證的區(qū)別

目前全文是翻譯的,講的主要是 cookie 驗證和 token 驗證的區(qū)別,cookie 驗證準確的說是利用 cookie 來作為媒介,存儲 session ID 進行驗證,token 其實也可以借助 cookie 來存儲,不過下文中提到的 cookie 驗證主要是指 session ID 存儲到 cookie 中進行的驗證。token 驗證主要是指 token 存儲在 Authorization Header 中進行的驗證。
這個翻譯并不是完全按照原本逐字意譯,有的是我看了原本以后根據(jù)自己的理解寫了出來,同時省略了一些我認為不重要的內(nèi)容,加了一點我自己的筆記和疑問的地方。
原文地址:https://auth0.com/blog/cookies-vs-tokens-definitive-guide/

下面是譯文:


cookie-token-auth.png

Cookie
cookie 驗證是用于長時間用戶驗證,cookie 驗證是有狀態(tài)的,意味著驗證記錄或者會話需要一直在服務(wù)端和客戶端保持。服務(wù)器需要保持對數(shù)據(jù)庫活動會話的追蹤,當在前端創(chuàng)建了一個 cookie,cookie 中包含了一個 session 標識符。傳統(tǒng) cookie 會話的驗證流程:

  • 用戶登錄,輸入賬號密碼

  • 服務(wù)器驗證用戶賬號密碼正確,創(chuàng)建一個 session 存儲在數(shù)據(jù)庫(或者 redis)

  • 將 session ID 放進 cookie 中,被存儲在用戶瀏覽器中。

  • 再次發(fā)起請求,服務(wù)器直接通過 session ID 對用戶進行驗證

  • 一旦用戶登出,則 session 在客戶端和服務(wù)器端都被銷毀

Token
token 驗證是無狀態(tài)的,服務(wù)器不記錄哪些用戶登錄了或者哪些 JWT 被發(fā)布了,而是每個請求都帶上了服務(wù)器需要驗證的 token,token 放在了 Authorization header 中,形式是 Bearer { JWT },但是也可以在 post body 里發(fā)送,甚至作為 query parameter。
驗證流程:

  • 用戶輸入登錄信息

  • 服務(wù)器判斷登錄信息正確,返回一個 token

  • token 存儲在客戶端,大多數(shù)通常在 local storage,但是也可以存儲在 session storage 或者 cookie 中。

  • 接著發(fā)起請求的時候?qū)?token 放進 Authorization header,或者同樣可以通過上面的方式。

  • 服務(wù)器端解碼 JWT 然后驗證 token,如果 token 有效,則處理該請求。

  • 一旦用戶登出,token 在客戶端被銷毀,不需要經(jīng)過服務(wù)器端。

Token 驗證的優(yōu)勢

  • 無狀態(tài),可擴展和解耦
    使用 token 而不是 cookie 的最大優(yōu)點應(yīng)該就是無狀態(tài),后端不需要保持對 token 的記錄,每個 token 都是獨立的,包含了檢查其有效性的所有數(shù)據(jù),并通過申明傳達了用戶信息。
    服務(wù)器端的工作只需要在登錄成功后,生成(或者 sign,簽署) token,或者驗證傳入的 token 是否有效。有時候甚至不需要生成 token,第三方服務(wù)比如 Auth0 可以處理 token 的簽發(fā),服務(wù)器只需要驗證 token 的有效性就可以。

  • 跨域和 CORS
    cookie 能很好的處理單域和子域,但是遇到跨域的問題就會變得難以處理。而使用 token 的 CORS 可以很好的處理跨域的問題。由于每次發(fā)送請求到后端,都需要檢查 JWT,只要它們被驗證通過就可以處理請求。

  • 在 JWT 中存儲數(shù)據(jù)
    當使用 cookie 進行驗證時,你是將 session id 存儲到 cookie 里,JWT 允許你存儲任何類型的元數(shù)據(jù),只要是合法的 JSON。你可以在里面添加任何數(shù)據(jù),可以只有用戶 ID 和到期日,也可以添加其它的比如郵件地址,域名等等。
    比如:加入你有一個 API 是 /api/orders ,用于取回最新的訂單,但是只有 admin 角色的用戶可以獲取到這些數(shù)據(jù)。在基于 cookie 的驗證中,一旦請求被創(chuàng)建,就需要先去訪問數(shù)據(jù)庫去驗證 session 是否正確(現(xiàn)在應(yīng)該都是存儲到 redis 里了,不會存數(shù)據(jù)庫里了),另外還要去獲取數(shù)據(jù)庫里的用戶權(quán)限去校驗用戶是否擁有 admin 的權(quán)限(這個應(yīng)該是根據(jù)用戶 role_id 查看權(quán)限是否是 admin),最后才是調(diào)用訂單信息。而使用 JWT 的話,可以將用戶角色放進 JWT 內(nèi),所以只要驗證通過了,就可以直接調(diào)用訂單信息。

  • 移動平臺
    現(xiàn)代的 API 不僅僅和瀏覽器交互,正確編寫一個 API 可以同時支持瀏覽器,還有原生移動平臺,比如 IOS 或者 Android。原生移動平臺并不一定和 cookie 能良好的兼容,在使用中會存在一些限制和需要注意的地方。另一方面,token 更容易在 IOS 和 Android 上實現(xiàn),Token 也更容易實現(xiàn)物聯(lián)網(wǎng)應(yīng)用程序和服務(wù),沒有 Cookie 存儲的概念。

共同的問題
這里介紹一些常見的問題,或者在令牌 token 的情況下出現(xiàn)時經(jīng)常出現(xiàn)。這里的關(guān)鍵重點將是安全性,但我們將介紹有關(guān) token 大小,存儲和加密的用例。

  • JWT 大小
    token 最大的缺點就是它的大小,最小的它都比 cookie 要大,如果 token 中包含很多聲明,那問題就會變得比較嚴重,畢竟向服務(wù)器發(fā)送的每個請求都要有這個 token。(意思應(yīng)該是太大了會導(dǎo)致請求緩慢)
  • 哪里存儲 token
    通常 JWT 被存儲在瀏覽器的 local storage 中并且能夠很好的運用,但是這樣存儲也會有問題,不像 cookie,local storage 被沙盒化到特定域,其區(qū)域不能被任何其他域訪問,包括子域。
    你可以存儲 token 在 cookie 中,但是 cookie 最大的大小也只有 4kb,所以如果你有許多聲明的時候可能會存儲不夠,session storage 就更不用說了,會話斷開就被清除掉了。
    (個人記錄:由于JWT前兩個字符串采用base64進行編碼,所以內(nèi)容越多,編碼字符串長度越長)
  • XSS 和 XSRF 防護
    保護用戶信息安全和服務(wù)器數(shù)據(jù)始終是首要任務(wù)。最常見的網(wǎng)絡(luò)攻擊就是 XSS 和 CSRF。
    如果用戶輸入或提交的信息沒有得到過濾的話,如果一些攻擊代碼可以在你訪問的域名下執(zhí)行,那你的 JWT token 會被泄露。與 CSRF 相比,XSS 會更容易處理(因為 XSS 很容易理解)。許多框架包括 Angular 等等,都會自動過濾掉 input 輸入的某些內(nèi)容且防止任意代碼執(zhí)行。如果框架本身不自帶這種過濾機制,可以采用一些插件比如 caja。這種過濾 input 輸入框是大部分框架和語言解決 XSS 問題的一個方式。
    如果你通過 local storage 使用 JWT,那么可以避免 CSRF,但是另一方面,如果你用 cookie 來存儲 JWT,那就需要防護 CSRF,CSRF 并不像 XSS 攻擊那么好理解。解釋 CSRF 攻擊可能會非常耗時。為了避免過度簡化,防止 CSRF 攻擊,你的服務(wù)器會和客戶端建立會話后,會生成一個唯一的 token(這不是 JWT)。然后隨時將數(shù)據(jù)提交到你的服務(wù)器,隱藏的 input 將會包含這個 token,服務(wù)器將會檢查這個 token 以確保 token 匹配。不夠我們是建議將 JWT 存儲在 local storage 中,你也不太需要擔心 CSRF 攻擊的問題。
    其中一個最好的保護用戶和服務(wù)器的方法就是有一個給 token 一個短期過期時間,這樣即使 token 被其他人獲取,但是也會很快不能再用。此外,你可以維護一個受攻擊的 token 黑名單,不允許這些黑名單的 token 訪問系統(tǒng)。最后,還可以統(tǒng)一更改 token 算法,讓所有 token 都失效,并讓用戶重新登錄系統(tǒng),不過這種方法一般不推薦,只有在被攻擊比較嚴重的情況下使用。
  • token Are Signed,Not Encrypted
    一個 JWT 是由三部分構(gòu)成:header,payload,signature。
    header: 算法和 token 類型,如
    { "alg": "HS256", "typ": "JWT"}
    payload: 數(shù)據(jù),如
    { "sub": "12", "name": "Ado Kukic", "admin": true}
    驗證簽名
HMACSHA256(
base64UrlEncode(header)+"." +
base64UrlEncode(payload),
secret
)

JWT 的格式為 header.payload.signature
,如果我們需要通過 HMACSHA256 算法簽發(fā)一個 JWT ,如果 secret 是 'shhhh' 以及 payload 是
{ "sub": "1234567890", "name": "Ado Kukic", "admin": true}
則 JWT 為
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFkbyBLdWtpYyIsImFkbWluIjp0cnVlLCJpYXQiOjE0NjQyOTc4ODV9.Y47kJvnHzU9qeJIN48_bVna6O0EDFiMiQ9LpNVDFymM

(疑問:secret 在這里是干嘛的)
這里有一個非常重要的提醒,token 是通過 HMACSHA256 算法生成,header 和 payload 是 Base64URL 編碼,這不是加密。如果你去訪問 jwt.io 網(wǎng)站,粘貼 token 以及選擇 HMACSHA256 算法,可以解析出 token 讀取它詳細的內(nèi)容。因此里面不能攜帶一些敏感數(shù)據(jù),比如密碼,絕對不能存儲在 payload 中。
如果你必須存儲敏感信息在 payload 中,或者使 JWT 被隱藏,你可以使用 JWE(JSON Web Encryption)。JWE 允許你去加密 JWT 的內(nèi)容,讓其除了服務(wù)器以外的任何人都不可讀。JOSE 為 JWE 提供了一個很好的框架,并為許多流行框架(包括 NodeJS 和 Java)提供了 SDK。

token 驗證在 Auth0 上的實踐
未完待續(xù)...

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,619評論 6 539
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,155評論 3 425
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,635評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,539評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,255評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,646評論 1 326
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,655評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,838評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,399評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,146評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,338評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,893評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,565評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,983評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,257評論 1 292
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,059評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,296評論 2 376

推薦閱讀更多精彩內(nèi)容