一、為什麼Cookie需要防篡改
為什麼要做Cookie防篡改,一個重要原因是 Cookie中儲存有判斷當前登陸使用者會話資訊(Session)的會話票據-SessionID和一些使用者資訊。 當發起一個HTTP請求,HTTP請求頭會帶上Cookie,Cookie裡面就包含有SessionID。 後端服務根據SessionID,去獲取當前的會話資訊。如果會話資訊存在,則代表該請求的使用者已經登陸。 伺服器根據登陸使用者的許可權,返回請求的資料到瀏覽器端。
因為Cookie是儲存在客戶端,使用者可以隨意修改。所以,存在一定的安全隱患。
二、例子
username
是為了通俗易懂地解釋這個概念,實際專案都不會這麼做的,周知。
- 使用者
wall
在瀏覽器端輸入使用者名稱密碼,發起POST請求到後端伺服器。後端伺服器驗證合法,返回Response,並Set-Cookie
為sessionid=***;username=wall;
。 - 瀏覽器端在接收到HTTP響應後,發現
Set-Cookie
,將其存入本地記憶體或硬碟中。 - 瀏覽器端再次發起請求,帶上Cookie資訊
sessionid=***;username=wall;
,請求修改自己的頭像資訊。 - 伺服器根據
sessionid
驗證當前使用者已登陸,根據username
,查詢資料庫中的對應資料,修改頭像資訊。
如果當前使用者知道username
的作用,修改username=pony
。再次發起請求,則伺服器接收到請求後,會去修改username
為pony
的資料。
這樣,就暴露出資料被惡意篡改的風險。
三、防篡改簽名
伺服器為每個Cookie項生成簽名。如果使用者篡改Cookie,則與簽名無法對應上。以此,來判斷資料是否被篡改。
原理如下:
- 服務端提供一個簽名生成演算法
secret
- 根據方法生成簽名
secret(wall)=34Yult8i
- 將生成的簽名放入對應的Cookie項
username=wall|34Yult8i
。其中,內容和簽名用|
隔開。 - 服務端根據接收到的內容和簽名,校驗內容是否被篡改。
舉個例子:
比如伺服器接收到請求中的Cookie項username=pony|34Yult8i
,然後使用簽名生成演算法secret(pony)=666
。
演算法得到的簽名666
和請求中資料的簽名不一致,則證明資料被篡改。
四、敏感資料的保護
鑑於Cookie的安全性隱患,敏感資料都應避免儲存在Cookie。 應該根據SessionID,將敏感資料儲存在後端。取資料時,根據SessionID去後端伺服器獲取即可。 另外,對一些重要的Cookie項,應該生成對應的簽名,來防止被惡意篡改。
喜歡我文章的朋友,可以通過以下方式關注我:
- 「star」 或 「watch」 我的GitHub blog
- RSS訂閱我的個人部落格:王先生的基地