黑客都知道的Cookie、Session、Token、JWT

2022-01-02 網絡安全編程與黑客程式設計師

https://juejin.im/post/5e055d9ef265da33997a42cc

什麼是認證(Authentication)什麼是授權(Authorization)什麼是憑證(Credentials)什麼是 Cookie

HTTP 是無狀態的協議(對於事務處理沒有記憶能力,每次客戶端和服務端會話完成時,服務端不會保存任何會話信息):每個請求都是完全獨立的,服務端無法確認當前訪問者的身份信息,無法分辨上一次的請求發送者和這一次的發送者是不是同一個人。所以伺服器與瀏覽器為了進行會話跟蹤(知道是誰在訪問我),就必須主動的去維護一個狀態,這個狀態用於告知服務端前後兩個請求是否來自同一瀏覽器。而這個狀態需要通過 cookie 或者 session 去實現。

cookie 存儲在客戶端: cookie 是伺服器發送到用戶瀏覽器並保存在本地的一小塊數據,它會在瀏覽器下次向同一伺服器再發起請求時被攜帶並發送到伺服器上。

cookie 是不可跨域的: 每個 cookie 都會綁定單一的域名,無法在別的域名下獲取使用,一級域名和二級域名之間是允許共享使用的靠的是 domain)

cookie 重要的屬性

屬性

說明



name=value

鍵值對,設置 Cookie 的名稱及相對應的值,都必須是字符串類型

如果值為 Unicode 字符,需要為字符編碼。

如果值為二進位數據,則需要使用 BASE64 編碼。
| | domain | 指定 cookie 所屬域名,默認是當前域名 | | path | 指定 cookie 在哪個路徑(路由)下生效,默認是 '/'
如果設置為 /abc,則只有 /abc 下的路由可以訪問到該 cookie,如:/abc/read。| | maxAge | cookie 失效的時間,單位秒。如果為整數,則該 cookie 在 maxAge 秒後失效。如果為負數,該 cookie 為臨時 cookie ,關閉瀏覽器即失效,瀏覽器也不會以任何形式保存該 cookie 。如果為 0,表示刪除該 cookie 。默認為 -1。

比 expires 好用
| | expires | 過期時間,在設置的某個時間點後該 cookie 就會失效。
一般瀏覽器的 cookie 都是默認儲存的,當關閉瀏覽器結束這個會話的時候,這個 cookie 也就會被刪除 | | secure | 該 cookie 是否僅被使用安全協議傳輸。安全協議有 HTTPS,SSL 等,在網絡上傳輸數據之前先將數據加密。默認為 false。
當 secure 值為 true 時,cookie 在 HTTP 中是無效,在 HTTPS 中才有效。| | httpOnly | 如果給某個 cookie 設置了 httpOnly 屬性,則無法通過 JS 腳本 讀取到該 cookie 的信息,但還是能通過 Application 中手動修改 cookie,所以只是在一定程度上可以防止 XSS 攻擊,不是絕對的安全 |

什麼是 Session

session 認證流程:

用戶第一次請求伺服器的時候,伺服器根據用戶提交的相關信息,創建對應的 Session

請求返回時將此 Session 的唯一標識信息 SessionID 返回給瀏覽器

瀏覽器接收到伺服器返回的 SessionID 信息後,會將此信息存入到 Cookie 中,同時 Cookie 記錄此 SessionID 屬於哪個域名

當用戶第二次訪問伺服器的時候,請求會自動判斷此域名下是否存在 Cookie 信息,如果存在自動將 Cookie 信息也發送給服務端,服務端會從 Cookie 中獲取 SessionID,再根據 SessionID 查找對應的 Session 信息,如果沒有找到說明用戶沒有登錄或者登錄失效,如果找到 Session 證明用戶已經登錄可執行後面操作。

根據以上流程可知,SessionID 是連接 Cookie 和 Session 的一道橋梁,大部分系統也是根據此原理來驗證用戶登錄狀態。

Cookie 和 Session 的區別

安全性: Session 比 Cookie 安全,Session 是存儲在伺服器端的,Cookie 是存儲在客戶端的。

存取值的類型不同:Cookie 只支持存字符串數據,想要設置其他類型的數據,需要將其轉換成字符串,Session 可以存任意數據類型。

有效期不同: Cookie 可設置為長時間保持,比如我們經常使用的默認登錄功能,Session 一般失效時間較短,客戶端關閉(默認情況下)或者 Session 超時都會失效。

存儲大小不同: 單個 Cookie 保存的數據不能超過 4K,Session 可存儲數據遠高於 Cookie,但是當訪問量過多,會佔用過多的伺服器資源。

什麼是 Token(令牌)Acesss Token

客戶端使用用戶名跟密碼請求登錄

服務端收到請求,去驗證用戶名與密碼

驗證成功後,服務端會籤發一個 token 並把這個 token 發送給客戶端

客戶端收到 token 以後,會把它存儲起來,比如放在 cookie 裡或者 localStorage 裡

客戶端每次向服務端請求資源的時候需要帶著服務端籤發的 token

服務端收到請求,然後去驗證客戶端請求裡面帶著的 token ,如果驗證成功,就向客戶端返回請求的數據

每一次請求都需要攜帶 token,需要把 token 放到 HTTP 的 Header 裡

基於 token 的用戶認證是一種服務端無狀態的認證方式,服務端不用存放 token 數據。用解析 token 的計算時間換取 session 的存儲空間,從而減輕伺服器的壓力,減少頻繁的查詢資料庫

token 完全由應用管理,所以它可以避開同源策略

Refresh Token

另外一種 token——refresh token

refresh token 是專用於刷新 access token 的 token。如果沒有 refresh token,也可以刷新 access token,但每次刷新都要用戶輸入登錄用戶名與密碼,會很麻煩。有了 refresh token,可以減少這個麻煩,客戶端直接用 refresh token 去更新 access token,無需用戶進行額外的操作。

Access Token 的有效期比較短,當 Acesss Token 由於過期而失效時,使用 Refresh Token 就可以獲取到新的 Token,如果 Refresh Token 也失效了,用戶就只能重新登錄了。

Refresh Token 及過期時間是存儲在伺服器的資料庫中,只有在申請新的 Acesss Token 時才會驗證,不會對業務接口響應時間造成影響,也不需要向 Session 一樣一直保持在內存中以應對大量的請求。

Token 和 Session 的區別

Session 是一種記錄伺服器和客戶端會話狀態的機制,使服務端有狀態化,可以記錄會話信息。而 Token 是令牌訪問資源接口(API)時所需要的資源憑證。Token 使服務端無狀態化,不會存儲會話信息。

Session 和 Token 並不矛盾,作為身份認證 Token 安全性比 Session 好,因為每一個請求都有籤名還能防止監聽以及重放攻擊,而 Session 就必須依賴鏈路層來保障通訊安全了。如果你需要實現有狀態的會話,仍然可以增加 Session 來在伺服器端保存一些狀態。

所謂 Session 認證只是簡單的把 User 信息存儲到 Session 裡,因為 SessionID 的不可預測性,暫且認為是安全的。而 Token ,如果指的是 OAuth Token 或類似的機制的話,提供的是 認證 和 授權 ,認證是針對用戶,授權是針對 App 。其目的是讓某 App 有權利訪問某用戶的信息。這裡的 Token 是唯一的。不可以轉移到其它 App 上,也不可以轉到其它用戶上。Session 只提供一種簡單的認證,即只要有此 SessionID ,即認為有此 User 的全部權利。是需要嚴格保密的,這個數據應該只保存在站方,不應該共享給其它網站或者第三方 App。所以簡單來說:如果你的用戶數據可能需要和第三方共享,或者允許第三方調用 API 接口,用 Token 。如果永遠只是自己的網站,自己的 App,用什麼就無所謂了。

什麼是 JWT

JSON Web Token(簡稱 JWT)是目前最流行的跨域認證解決方案。

是一種認證授權機制

JWT 是為了在網絡應用環境間傳遞聲明而執行的一種基於 JSON 的開放標準(RFC 7519)。JWT 的聲明一般被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便於從資源伺服器獲取資源。比如用在用戶登錄上。

可以使用 HMAC 算法或者是 RSA 的公 / 私秘鑰對 JWT 進行籤名。因為數字籤名的存在,這些傳遞的信息是可信的。

阮一峰老師的 JSON Web Token 入門教程 講的非常通俗易懂,這裡就不再班門弄斧了

生成 JWT

jwt.io/
www.jsonwebtoken.io/

JWT 的原理

JWT 認證流程:

用戶輸入用戶名 / 密碼登錄,服務端認證成功後,會返回給客戶端一個 JWT

客戶端將 token 保存到本地(通常使用 localstorage,也可以使用 cookie)

當用戶希望訪問一個受保護的路由或者資源的時候,需要請求頭的 Authorization 欄位中使用 Bearer 模式添加 JWT,其內容看起來是下面這樣

Authorization: Bearer <token>

服務端的保護路由將會檢查請求頭 Authorization 中的 JWT 信息,如果合法,則允許用戶的行為

因為 JWT 是自包含的(內部包含了一些會話信息),因此減少了需要查詢資料庫的需要

因為 JWT 並不使用 Cookie 的,所以你可以使用任何域名提供你的 API 服務而不需要擔心跨域資源共享問題(CORS)

因為用戶的狀態不再存儲在服務端的內存中,所以這是一種無狀態的認證機制

JWT 的使用方式方式一方式二方式三

http://www.example.com/user?token=xxx

項目中使用 JWT

項目地址

Token 和 JWT 的區別

相同:

區別:

常見的前後端鑑權方式

Session-Cookie

Token 驗證(包括 JWT,SSO)

OAuth2.0(開放授權)

常見的加密算法

注意:

以上不能保證數據被惡意篡改,原始數據和哈希值都可能被惡意篡改,要保證不被篡改,可以使用 RSA 公鑰私鑰方案,再配合哈希值。

哈希算法主要用來防止計算機傳輸過程中的錯誤,早期計算機通過前 7 位數據第 8 位奇偶校驗碼來保障(12.5% 的浪費效率低),對於一段數據或文件,通過哈希算法生成 128bit 或者 256bit 的哈希值,如果校驗有問題就要求重傳。

常見問題使用 cookie 時需要考慮的問題

因為存儲在客戶端,容易被客戶端篡改,使用前需要驗證合法性

不要存儲敏感數據,比如用戶密碼,帳戶餘額

使用 httpOnly 在一定程度上提高安全性

儘量減少 cookie 的體積,能存儲的數據量不能超過 4kb

設置正確的 domain 和 path,減少數據傳輸

cookie 無法跨域

一個瀏覽器針對一個網站最多存 20 個 Cookie,瀏覽器一般只允許存放 300 個 Cookie

移動端對 cookie 的支持不是很好,而 session 需要基於 cookie 實現,所以移動端常用的是 token

使用 session 時需要考慮的問題

將 session 存儲在伺服器裡面,當用戶同時在線量比較多時,這些 session 會佔據較多的內存,需要在服務端定期的去清理過期的 session

當網站採用集群部署的時候,會遇到多臺 web 伺服器之間如何做 session 共享的問題。因為 session 是由單個伺服器創建的,但是處理用戶請求的伺服器不一定是那個創建 session 的伺服器,那麼該伺服器就無法拿到之前已經放入到 session 中的登錄憑證之類的信息了。

當多個應用要共享 session 時,除了以上問題,還會遇到跨域問題,因為不同的應用可能部署的主機不一樣,需要在各個應用做好 cookie 跨域的處理。

sessionId 是存儲在 cookie 中的,假如瀏覽器禁止 cookie 或不支持 cookie 怎麼辦? 一般會把 sessionId 跟在 url 參數後面即重寫 url,所以 session 不一定非得需要靠 cookie 實現

移動端對 cookie 的支持不是很好,而 session 需要基於 cookie 實現,所以移動端常用的是 token

使用 token 時需要考慮的問題

如果你認為用資料庫來存儲 token 會導致查詢時間太長,可以選擇放在內存當中。比如 redis 很適合你對 token 查詢的需求。

token 完全由應用管理,所以它可以避開同源策略

token 可以避免 CSRF 攻擊 (因為不需要 cookie 了)

移動端對 cookie 的支持不是很好,而 session 需要基於 cookie 實現,所以移動端常用的是 token

使用 JWT 時需要考慮的問題

因為 JWT 並不依賴 Cookie 的,所以你可以使用任何域名提供你的 API 服務而不需要擔心跨域資源共享問題(CORS)

JWT 默認是不加密,但也是可以加密的。生成原始 Token 以後,可以用密鑰再加密一次。

JWT 不加密的情況下,不能將秘密數據寫入 JWT。

JWT 不僅可以用於認證,也可以用於交換信息。有效使用 JWT,可以降低伺服器查詢資料庫的次數。

JWT 最大的優勢是伺服器不再需要存儲 Session,使得伺服器認證鑑權業務可以方便擴展。但這也是 JWT 最大的缺點:由於伺服器不需要存儲 Session 狀態,因此使用過程中無法廢棄某個 Token 或者更改 Token 的權限。也就是說一旦 JWT 籤發了,到期之前就會始終有效,除非伺服器部署額外的邏輯。

JWT 本身包含了認證信息,一旦洩露,任何人都可以獲得該令牌的所有權限。為了減少盜用,JWT 的有效期應該設置得比較短。對於一些比較重要的權限,使用時應該再次對用戶進行認證。

JWT 適合一次性的命令認證,頒發一個有效期極短的 JWT,即使暴露了危險也很小,由於每次操作都會生成新的 JWT,因此也沒必要保存 JWT,真正實現無狀態。

為了減少盜用,JWT 不應該使用 HTTP 協議明碼傳輸,要使用 HTTPS 協議傳輸。

使用加密算法時需要考慮的問題

絕不要以明文存儲密碼

永遠使用 哈希算法 來處理密碼,絕不要使用 Base64 或其他編碼方式來存儲密碼,這和以明文存儲密碼是一樣的,使用哈希,而不要使用編碼。編碼以及加密,都是雙向的過程,而密碼是保密的,應該只被它的所有者知道, 這個過程必須是單向的。哈希正是用於做這個的,從來沒有解哈希這種說法, 但是編碼就存在解碼,加密就存在解密。

絕不要使用弱哈希或已被破解的哈希算法,像 MD5 或 SHA1 ,只使用強密碼哈希算法。

絕不要以明文形式顯示或發送密碼,即使是對密碼的所有者也應該這樣。如果你需要 「忘記密碼」 的功能,可以隨機生成一個新的 一次性的(這點很重要)密碼,然後把這個密碼發送給用戶。

分布式架構下 session 共享方案1. session 複製

優點: 可容錯,各個伺服器間 session 能夠實時響應。
缺點: 會對網絡負荷造成一定壓力,如果 session 量大的話可能會造成網絡堵塞,拖慢伺服器性能。

2. 粘性 session /IP 綁定策略

優點: 簡單,不需要對 session 做任何處理。
缺點: 缺乏容錯性,如果當前訪問的伺服器發生故障,用戶被轉移到第二個伺服器上時,他的 session 信息都將失效。
適用場景: 發生故障對客戶產生的影響較小;伺服器發生故障是低概率事件 。
實現方式: 以 Nginx 為例,在 upstream 模塊配置 ip_hash 屬性即可實現粘性 session。

3. session 共享(常用)

4. session 持久化

優點: 伺服器出現問題,session 不會丟失
缺點: 如果網站的訪問量很大,把 session 存儲到資料庫中,會對資料庫造成很大壓力,還需要增加額外的開銷維護資料庫。

只要關閉瀏覽器 ,session 真的就消失了?

不對。對 session 來說,除非程序通知伺服器刪除一個 session,否則伺服器會一直保留,程序一般都是在用戶做 log off 的時候發個指令去刪除 session。
然而瀏覽器從來不會主動在關閉之前通知伺服器它將要關閉,因此伺服器根本不會有機會知道瀏覽器已經關閉,之所以會有這種錯覺,是大部分 session 機制都使用會話 cookie 來保存 session id,而關閉瀏覽器後這個 session id 就消失了,再次連接伺服器時也就無法找到原來的 session。如果伺服器設置的 cookie 被保存在硬碟上,或者使用某種手段改寫瀏覽器發出的 HTTP 請求頭,把原來的 session id 發送給伺服器,則再次打開瀏覽器仍然能夠打開原來的 session。
恰恰是由於關閉瀏覽器不會導致 session 被刪除,迫使伺服器為 session 設置了一個失效時間,當距離客戶端上一次使用 session 的時間超過這個失效時間時,伺服器就認為客戶端已經停止了活動,才會把 session 刪除以節省存儲空間。


相關焦點

  • 熬夜徹底搞懂Cookie Session Token JWT
    記憶力不好的優點就是一個字「快」;缺點也很明顯,需要借靠 cookie、session 、token等機制將客戶端多次請求關聯起來。想像一下如果沒有 cookie、session、token 這樣的機制,我們在網站上每次點擊都需要重新輸入密碼認證,這樣槽糕的體驗你還願意繼續用嗎?
  • Cookie、Session、Token與JWT解析
    所以伺服器與瀏覽器為了進行會話跟蹤(知道是誰在訪問我),就必須主動的去維護一個狀態,這個狀態用於告知服務端前後兩個請求是否來自同一瀏覽器。而這個狀態需要通過 cookie 或者 session 去實現。
  • Cookie、Session、Token、JWT終於講清楚了
    所以伺服器與瀏覽器為了進行會話跟蹤(知道是誰在訪問我),就必須主動的去維護一個狀態,這個狀態用於告知服務端前後兩個請求是否來自同一瀏覽器。而這個狀態需要通過 cookie 或者 session 去實現。
  • 詳解 Cookie,Session,Token
    本文主要講解cookie,session, token 這三種是如何管理會話的;cookiecookie 是一個非常具體的東西,指的就是瀏覽器裡面能永久存儲的一種數據。跟伺服器沒啥關係,僅僅是瀏覽器實現的一種數據存儲功能。
  • 前端鑑權 5 兄弟:cookie、session、token、jwt、單點登錄
    本文你將看到:基於 HTTP 的前端鑑權背景cookie 為什麼是最方便的存儲方案,有哪些操作 cookie 的方式session 方案是如何實現的,存在哪些問題token 方案是如何實現的,如何進行編碼和防篡改?jwt 是做什麼的?
  • 還傻傻分不清 Cookie、Session、Token、JWT?
    所以伺服器與瀏覽器為了進行會話跟蹤(知道是誰在訪問我),就必須主動的去維護一個狀態,這個狀態用於告知服務端前後兩個請求是否來自同一瀏覽器。而這個狀態需要通過 cookie 或者 session 去實現。
  • 測開之Cookie、Session、Token、JWT的區別
    所以伺服器與瀏覽器為了進行會話跟蹤(知道是誰在訪問我),就必須主動的去維護一個狀態,這個狀態用於告知服務端前後兩個請求是否來自同一瀏覽器。而這個狀態需要通過 cookie 或者 session 去實現。
  • 前端鑑權:cookie、session、token、jwt、單點登錄全貢獻出來了!
    jwt 是做什麼的?refresh token 的實現和意義session 和 token 有什麼異同和優缺點單點登錄是什麼?實現思路和在瀏覽器下的處理從狀態說起HTTP 無狀態我們知道,HTTP 是無狀態的。也就是說,HTTP 請求方和響應方間無法維護狀態,都是一次性的,它不知道前後的請求都發生了什麼。但有的場景下,我們需要維護狀態。
  • 前端鑑權必須了解的5個兄弟:cookie、session、token、jwt、單點登錄
    refresh token 的實現和意義session 和 token 有什麼異同和優缺點從狀態說起「HTTP 無狀態」我們知道,HTTP 是無狀態的。也就是說,HTTP 請求方和響應方間無法維護狀態,都是一次性的,它不知道前後的請求都發生了什麼。
  • 前端鑑權必須了解的 5 個兄弟:cookie、session、token、jwt、單點登錄
    jwt 是做什麼的?refresh token 的實現和意義session 和 token 有什麼異同和優缺點單點登錄是什麼?實現思路和在瀏覽器下的處理從狀態說起「HTTP 無狀態」我們知道,HTTP 是無狀態的。也就是說,HTTP 請求方和響應方間無法維護狀態,都是一次性的,它不知道前後的請求都發生了什麼。但有的場景下,我們需要維護狀態。
  • 還分不清 Cookie、Session、Token、JWT?一篇文章講清楚
    所以伺服器與瀏覽器為了進行會話跟蹤(知道是誰在訪問我),就必須主動的去維護一個狀態,這個狀態用於告知服務端前後兩個請求是否來自同一瀏覽器。而這個狀態需要通過 cookie 或者 session 去實現。cookie 存儲在客戶端: cookie 是伺服器發送到用戶瀏覽器並保存在本地的一小塊數據,它會在瀏覽器下次向同一伺服器再發起請求時被攜帶並發送到伺服器上。
  • 面試官:要不講講 Cookie、Session、Token、JWT之間的區別?
    所以伺服器與瀏覽器為了進行會話跟蹤(知道是誰在訪問我),就必須主動的去維護一個狀態,這個狀態用於告知服務端前後兩個請求是否來自同一瀏覽器。而這個狀態需要通過 cookie 或者 session 去實現。
  • 一文讀懂Cookie、Session、Token和JWT(建議收藏)
    所以伺服器與瀏覽器為了進行會話跟蹤(知道是誰在訪問我),就必須主動的去維護一個狀態,這個狀態用於告知服務端前後兩個請求是否來自同一瀏覽器。而這個狀態需要通過 cookie 或者 session 去實現。cookie 存儲在客戶端:cookie 是伺服器發送到用戶瀏覽器並保存在本地的一小塊數據,它會在瀏覽器下次向同一伺服器再發起請求時被攜帶並發送到伺服器上。
  • 你還傻傻分不清Cookie、Session、Token、JWT嗎?
    所以伺服器與瀏覽器為了進行會話跟蹤(知道是誰在訪問我),就必須主動的去維護一個狀態,這個狀態用於告知服務端前後兩個請求是否來自同一瀏覽器。而這個狀態需要通過 cookie 或者 session 去實現。
  • Session/Cookie/Token 還傻傻分不清?
    token 的介紹有誤,所以對 cookie,session, token 作了一下對比(文中token指jwt token)相信大家看完肯定有收穫!主要有以下三種方式1、session 複製A 生成 session 後複製到 B, C,這樣每臺機器都有一份 session,無論添加購物車的請求打到哪臺機器,由於 session 都能找到,故不會有問題
  • 面試必問:session,cookie和token的區別
    禁用cookie後還有其他方法存儲,比如放在url中現在大多都是Session + Cookie,但是只用session不用cookie,或是只用cookie,不用session在理論上都可以保持會話狀態。可是實際中因為多種原因,一般不會單獨使用用session只需要在客戶端保存一個id,實際上大量數據都是保存在服務端。
  • Golang初學之使用JWT認證(JSON Web Token)
    首先,要搞明白一個問題,token、cookie、session的區別。token、cookie、session的區別#0x001 Cookie Cookie總是保存在客戶端中,按在客戶端中的存儲位置,可分為內存Cookie和硬碟Cookie。
  • cookie、session、token區別
    token,session,cookie的概念和區別1.token是 服務經過計算發給客戶端的,服務不保存,每次客戶端來請求,經過解密等計算來驗證是否是自己下發的2.session是服務本地保存,發給客戶端,客戶端每次訪問都帶著,直接和服務的session比對3.cookie是保存在客戶端上的一些基本信息,服務不保存,每次請求時客戶端帶上cookie,裡面有一些帳戶密碼
  • 基於jwt的token驗證、原理及流程
    這個名字像是特指飛機上承載的貨品,這些有效信息包含三個部分標準中註冊的聲明 (建議但不強制使用) :exp: jwt的過期時間,這個過期時間必須要大於籤發時間nbf: 定義在什麼時間之前,該jwt都是不可用的.jti: jwt的唯一身份標識,主要用來作為一次性token,從而迴避重放攻擊。
  • 前後端接口鑑權全解 Cookie/Session/Token 的區別
    Session從 cookie 說到 session,是因為 session 才是真正的「信息」,如上面提到的,cookie 是容器,裡面裝著 PHPSESSID=298zf09hf012fh2;,這就是一個 session ID。不知道 session 和 session id 會不會讓你看得有點頭暈?