前後端分離技術:API驗證需求分析

前後端分離要解決的一個大問題就是信息安全,我們一起來分析應該如何實現?

一、使用session存在的問題:

  • session和cookie是爲了解決http無狀態的方案。session是用戶保存在服務器中的狀態信息,cookie中則保存jsessionId,請求服務器時,服務器讀取jsessionId從而確定用戶的身份信息,而session+cookie用在restful接口上破壞了其“無狀態”的特性,session運行時都是保存在內存中,而隨着認證用戶的增多,服務端的開銷會明顯增大。這也是restful最致力於通過“無狀態”解決的問題。如果使用session,那麼restful也就沒有什麼意義了

  • session降低了系統擴展性。用戶認證之後,服務端做認證記錄,如果認證的記錄被保存在內存中的話,這意味着用戶下次請求還必須要請求在這臺服務器上,這樣才能拿到授權的資源,這樣在分佈式的應用上,相應的限制了負載均衡器的能力。這也意味着限制了應用的擴展能力

  • cookie不安全,很容易導致跨站請求僞造攻擊(CSRF)

二、使用token存在的問題:

  • 如何確定token的過期時間?如果token的有效期過短,很容易造成用戶用着用着就掉線的情況,降低用戶體驗。但目前看來好像並沒有太好的辦法,只能儘量延長token的有效期,或者每隔一次前端自動向服務端請求一次token

  • token爲什麼要刷新嗎?

首先 Basic Auth 是一種最簡單的認證方法,但是由於每次請求都帶用戶名和密碼,頻繁的傳輸肯定不安全,所以纔有 cookies 和 session 的運用。如果 token 不刷新,那麼 token 就相當於上面的用戶名 + 密碼,只要獲取到了,就可以一直盜用,因此 token 設置有效期並能夠進行刷新是必要的。

  • token有效期多久合適,刷新頻率多久合適?

有效期越長,風險性越高,有效性越短,刷新頻率越高,刷新就會存在刷新開銷,所以這需要綜合考慮。而且 web 端應該設置爲分鐘級和小時級,而移動端應該設置爲天級和周級

  • token相對於Cookie+Session的優點,主要有下面兩個:

        (1)、 CSRF 攻擊

         這個原理不多做介紹,構成這個攻擊的原因,就在於 Cookie + Session 的鑑權方式中,cookie 中的 session_id是由瀏覽器自動攜帶發送到服務端的,藉助這個特性,攻擊者就可以通過讓用戶誤點攻擊鏈接,達到攻擊效果。而 token 是通過客戶端本身邏輯作爲動態參數加到請求中的,token 也不會輕易泄露出去,因此 token 在 CSRF 防禦方面存在天然優勢。

          (2)、適合移動應用

        移動端上不支持 cookie,而 token 只要客戶端能夠進行存儲就能夠使用,因此 token 在移動端上也具有優勢。

 三、解決方案:基於JWT-Auth的token驗證體系

JWT 全稱 JSON Web Tokens ,是一個非常輕巧的規範。這個規範允許我們使用 JWT 在用戶和服務器之間傳遞安全可靠的信息。它的兩大使用場景是:認證和數據交換。

token主要有三種:

  1. 自定義的 token:開發者根據業務邏輯自定義的 token
  2. JWT:JSON Web Token,定義在 RFC 7519 中的一種 token 規範
  3. Oauth2.0:定義在 RFC 6750 中的一種授權規範,但這其實並不是一種 token,只是其中也有用到 token

jwt-auth的用途:
1、一是判斷登陸狀態(auth),如未登陸則被攔截,然後轉交給登陸模塊,這需要一箇中間件來完成。
2、二是管理登陸,即登陸邏輯login:

  • 登陸成功則發送給用戶一個授權token
  • logout退出登陸,銷燬token
  • 忘記密碼forgetPassword
  • 註冊signUp等

JWT的使用有兩種方式:

  • 加到 url 中:?token=你的token
  • 加到 header 中,建議用這種,因爲在 https 情況下更安全:Authorization:Bearer 你的token

JWT在客戶端的存儲有三種方式:

  • LocalStorage
  • SessionStorage
  • Cookie (缺點:不能設置 HTTPonly,因爲沒開 HTTPonly,所以要注意防範 XSS 漏洞)

    推薦使用第三種,因爲第一二種存在跨域讀取限制,而 Cookie 可以使用不同的跨域策略

Cookie的跨域策略(繼承關係)

子可以讀父,但是父不可以讀子,兄弟之間不能互相訪問。舉例如下:

  1. 子可以讀父:a.xxx.com 和 b.xxx.com 可以讀 xxx.com 的Cookie
  2. 父不可以讀子:xxx.com 不能讀 a.xxx.com 和 b.xxx.com 的Cookie
  3. 兄弟之間不能互相訪問:a.xxx.com 和 b.xxx.com 不能互相讀取Cookie

token存到Cookie裏,那我不是又變得和cookie+session一樣了嗎?

其實不然,因爲token存到cookie裏,只是用到了其存儲機制,而沒有利用其去鑑權。也就是說我只是簡單存一下,並沒有期望瀏覽器帶上 token 去鑑權,將 token 加入請求這部分操作還是需要我們手動進行的。

JWT相對於一般token的優點:

(1)、無狀態

     因爲 JWT 的有效期完全與其載荷中編碼的過期時間,服務端不維護任何狀態,因此 JWT一般情況下是無狀態的,無狀態最大的優勢在於三點:

  1. 節省服務器的資源:因爲服務端無需維護一個狀態,因此能夠節省服務端原先保存這些狀態所花費的資源
  2. 適合分佈式:因爲服務端無需維護狀態,因此如果服務端是多臺服務器組成的分佈式集羣,那麼無需像『有狀態』一樣互相同步各自的狀態。
  3. 時間換空間:因爲 token 的校驗時通過簽名校驗來進行的,簽名校驗消耗的是 CPU 時間,而『有狀態』是需要通過客戶端提供的憑據對服務端現有的狀態進行一次查詢,消耗的是 I/O 和內存、磁盤空間。通常對於一個 Web 服務來說,其屬於 I/O 密集型,因此通過時間換空間這一操作,可以提高整體的硬件使用率。

(2)、編碼數據

     因爲 JWT 能夠在載荷中編碼了部分信息,所以如果把常用數據編碼進去的話,能夠大大減少數據庫的查詢次數,不過有兩點需要額外注意的:

  1. 載荷信息是明文編碼的,所以不能編碼敏感信息在裏面,如果要編碼可以先加密再編碼進去
  2. token 在每次請求時都會進行傳輸,所以載荷中不能編碼過多的信息,否則會降低傳輸效率

JWT如何防止token被盜?
因爲 token 中包含了登陸狀態,因此一旦 token 被盜,那麼就會被人盜用身份。那麼 token 針對被盜的防範措施整理如下:

  • 使用 HTTPS 傳輸:從傳輸層的角度解決問題
  • HTTPOnly:從存儲層的角度解決問題,防止 XSS 攻擊竊取 cookie,但是這種方案其實存在問題,因爲這樣 js 就無法讀取 token 並把它加到 header 頭中了。所以不開啓 HTTPOnly 的話必須要額外注意防範 XSS 攻擊。
  • 在 token 中嵌入客戶端指紋:通過客戶端指紋,即使黑客盜取了你的 cookie,他也無法用你的 cookie 進行請求。
  • 設置較短的 token 有效期:這樣如果 token 被盜,只要超過一定時限就無法使用。

大家可以去參考某大神寫的文章:

JWT 超詳細分析: https://learnku.com/articles/17883

JWT 完整使用詳解:https://learnku.com/articles/10885/full-use-of-jwt

JWT 擴展具體實現詳解:https://learnku.com/articles/10889/detailed-implementation-of-jwt-extensions

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章