傳統的服務端有狀態Session至JWT的無狀態至OAuth2至OAuth2+JWT


采用令牌的方式可以讓用戶靈活地對第三方應用授權或者收回權限,OAuth2是OAuth協議的下一個版本,但不向下兼容OAuth 1.0。OAuth2關注客戶端開發者的簡易性,同時為Web應用、桌面應用、移動設備、起居室設備提供專門的認證流程,傳統的Web開發登錄認證一般都是基於Session的,但是前后端分離的架構中繼續使用Session會有很多不便,因為移動端要么不支持cookie(微信小程序),要么使用非常不便,對於這些問題,使用OAuth2認證都能解決。

OAuth2授權有4種模式,我們自己做前后端分離登錄就可以采用密碼模式。微服務中有一個特殊的場景,就是服務之間的調用,用密碼模式做鑒權是非常恰當不過的了

 

0.OAuth2中的角色都有哪些?

   0.1 資源擁有者
        可以是一個人也可以是一個公司實體,對資源持有的實體。

   0.2 資源服務
         受保護的資源,可以使用token令牌來訪問

   0.3 客戶端
         需要請求資源的應用客戶端,PC,APP

   0.4 認證服務
        發放令牌的服務,驗證資源所有者並獲得授權

 

 

1.為什么要用無狀態服務的代替有狀態服務的?

有狀態服務,即服務端需要記錄每次會話的客戶端信息,從而識別客戶端身份,根據用戶身份進行請求的處理,典型的設計如 Tomcat 中的 Session。例如登錄:用戶登錄后,我們把用戶的信息保存在服務端 session 中,並且給用戶一個 cookie 值,記錄對應的 session,然后下次請求,用戶攜帶 cookie 值來(這一步有瀏覽器自動完成),我們就能識別到對應 session,從而找到用戶的信息。這種方式目前來看最方便,但是也有一些缺陷,如下:

  • 服務端保存大量數據,增加服務端壓力
  • 服務端保存用戶狀態,不支持集群化部

2.無狀態性有哪些好處呢?

  • 客戶端請求不依賴服務端的信息,多次請求不需要必須訪問到同一台服務器
  • 服務端的集群和狀態對客戶端透明
  • 服務端可以任意的遷移和伸縮(可以方便的進行集群化部署)
  • 減小服務端存儲壓力

3.如何實現無狀態?無狀態的登陸流程:

  • 首先客戶端發送賬戶名/密碼到服務端進行認證
  • 認證通過后,服務端將用戶信息加密並且編碼成一個 token,返回給客戶端
  • 以后客戶端每次發送請求,都需要攜帶認證的 token
  • 服務端對客戶端發送來的 token 進行解密,判斷是否有效,並且獲取用戶登錄信息

4.JWT存在的問題:

  1. 續簽問題,這是被很多人詬病的問題之一,傳統的 cookie+session 的方案天然的支持續簽,但是 jwt 由於服務端不保存用戶狀態,因此很難完美解決續簽問題,如果引入 redis,雖然可以解決問題,但是 jwt 也變得不倫不類了。
  2. 注銷問題,由於服務端不再保存用戶信息,所以一般可以通過修改 secret 來實現注銷,服務端 secret 修改后,已經頒發的未過期的 token 就會認證失敗,進而實現注銷,不過畢竟沒有傳統的注銷方便。
  3. 密碼重置,密碼重置后,原本的 token 依然可以訪問系統,這時候也需要強制修改 secret。
  4. 基於第 2 點和第 3 點,一般建議不同用戶取不同 secret

5.單純的使用OAuth2的password模式有問題嗎?

我們知道授權服務器派發了 access_token 之后,客戶端拿着 access_token 去請求資源服務器,資源服務器要去校驗 access_token 的真偽,所以我們在資源服務器上配置了 RemoteTokenServices,讓資源服務器做遠程校驗

@Bean
RemoteTokenServices tokenServices() {
    RemoteTokenServices services = new RemoteTokenServices();
    services.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");
    services.setClientId("javaboy");
    services.setClientSecret("123");
    return services;
}

在高並發環境下這樣的校驗方式顯然是有問題的,如果結合 JWT,用戶的所有信息都保存在 JWT 中,這樣就可以有效的解決上面的問題

6. OAuth2中存儲令牌的方式:

我們可以把令牌存儲在內存中,但是如果部署多個服務,就會導致無法使用令牌的問題。 Spring Cloud Security中有兩種存儲令牌的方式可用於解決該問題,一種是使用Redis來存儲,另一種是使用JWT來存儲

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM