天天看點

Spring Cloud的OAuth2認證授權不再需要密碼模式了

舊的​​Spring Security OAuth2停止維護​​已經有一段時間了,99%的Spring Cloud微服務項目還在使用這些舊的體系,嚴重青黃不接。很多同學都在尋找新的解決方案,甚至還有念念不忘​​密碼模式​​​的,别想了,已經涼透了。胖哥也在前面寫了一篇​​解決思路的文章​​。好像還是不過瘾,今天看到這篇文章的同學有福了,問題将在這裡得到解決。

倉庫位址:https://github.com/NotFound403/id-server 

歡迎star,持續更新最先進的玩法

方案

目前這應該是Spring生态中最新的解決方案,沒有之一。先看下流程,微服務無關的其它的元件這裡先屏蔽了,剩下圖的幾個元件:

Spring Cloud的OAuth2認證授權不再需要密碼模式了

詳細流程為:

  • ①使用者向網關請求登入或者通過網關請求資源伺服器的資源。
  • ②網關發現使用者沒有授權發起基于OAuth2授權碼的OIDC流程,向授權伺服器Id Server發起授權請求。
  • ③授權伺服器Id Server收到授權請求重定向到使用者登入頁面要求使用者登入認證,以發起授權。
  • ④使用者輸入使用者名密碼進行登入認證。
  • ⑤Id Server授權伺服器處理使用者認證并重定向到網關約定的OAuth2 Redirect URI,這個過程屬于标準的OIDC授權碼流程。
  • ⑥網關獲得AccessToken和IdToken:
  • 如果最初發起的是登入就重定向到​

    ​/​

    ​。
  • 如果最初發起的是請求資源伺服器資源就令牌中繼重定向到對應的資源。
  • 資源伺服器通過⑦⑧兩個鍊路響應使用者的請求。

請注意,上述流程中生成的AccessToken和IdToken不允許提供給使用者側,否則會引起中間人攻擊,預設提供的是一個cookie政策,大部分情況下這種政策是夠用的,如果你需要自定義必須深刻了解其機制,你可以通過我的Spring Security OAuth2專欄進行學習。

具體實作

根據上面的方案,我們需要三個應用,分别是網關Spring Cloud Gateway應用、資源伺服器應用Resource Server和OAuth2授權伺服器Id Server。

Spring Cloud Gateway

Spring Cloud Gateway 應用,端口​

​8080​

​,它不僅僅是一個網關還是一個在授權伺服器Id Server注冊的OAuth2用戶端,通過Id Server你可以在一分鐘内完成配置。它需要配置到資源伺服器的路由規則和令牌中繼功能。核心配置為:

spring:
  application:
    name: gateway
  security:
    oauth2:
      client:
        registration:
          # 這裡為用戶端名稱可自行更改
          gatewayclient:
            client-id: e4da4a32-592b-46f0-ae1d-784310e88423
            # 密碼為注冊用戶端時的密碼
            client-secret: secret
            # 隻能選擇一個
            redirect-uri: http://127.0.0.1:8080/login/oauth2/code/gatewayclient
            # 其它兩種方式為refresh_token,client_credentials
            authorization-grant-type: authorization_code
            client-authentication-method: client_secret_basic
            scope: message.write,userinfo,message.read,openid
        provider:
          gatewayclient:
            # 要保證授權伺服器位址可以被用戶端通路
            issuer-uri: http://localhost:9000
  cloud:
    gateway:
      routes:
        - id: resource-server
          uri: http://127.0.0.1:8084
          predicates:
            - Path=/res/**
          filters:
            - TokenRelay      

Resource Server

資源伺服器就是我們平常編寫的業務接口的伺服器,端口這裡定義為​

​8084​

​,它需要內建Spring Security及其Resource Server元件。它要負責定義資源接口的通路權限,例如:

// 隻有message.read才有資格通路資源/res/foo
        httpSecurity.authorizeRequests()
                .antMatchers("/res/foo").hasAnyAuthority("SCOPE_message.read")      

另外它還要和授權伺服器Id Server通訊擷取AccessToken的解碼公鑰:

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          jwk-set-uri: http://localhost:9000/oauth2/jwks      

擷取解碼公鑰的原理在我的Spring Security OAuth2專欄有詳細介紹,這裡不再贅述。

Id Server

倉庫位址:https://github.com/NotFound403/id-server 歡迎star,歡迎貢獻代碼。

Id Server是一個基于Spring Authorization Server的開源的授權伺服器,它大大降低OAuth2授權伺服器的學習使用難度,提供UI控制台,動态權限控制,友善OAuth2用戶端管理,可一鍵生成Spring Security配置,開箱即用,少量配置修改就可部署,代碼開源,友善二次開發,支援OAuth2四種用戶端認證方式和三種授權模式。它是目前Spring安全生态中重要的組成部分,也是未來的技術發展趨勢,更多資訊請參閱Id Server項目倉庫的介紹。

Id Server在本文扮演的是OAuth2授權伺服器的角色,負責對授權請求進行處理,維護用戶端注冊資訊,授權使用者資訊,後續會加入IDP支援,各種三方登入的使用者也可以動态在這裡進行登入,就像這樣:

聯合登入

根據業務需要第三方OAuth2授權登入也能優雅的接入,當然,接入的登入方式需要OIDC或者OAuth2的支援。

DEMO以及使用方法

上述完整DEMO在Id Server的倉庫中的​

​samples​

​下。使用方法:

  • 拉取Id Server項目并加載依賴。
  • 在IntelliJ IDEA中依次單獨對​

    ​samples​

    ​檔案夾下的所有項目的​

    ​pom.xml​

    ​進行右鍵菜單選中Add As Maven Project,這一步很重要。
  • 依次啟動Id Server、gateway、resource-server三個項目。

測試登入

  • 浏覽器通路​

    ​​http://127.0.0.1:8080/login​​

    ​,點選​

    ​​http://localhost:9000​​

    ​。
  • 輸入使用者名密碼​

    ​user/user​

    ​。
  • 能檢視到認證資訊就證明成功了,再次重申,在生産中該資訊十分敏感,不應該直接對前端暴露。
  • 浏覽器通路​

    ​​http://127.0.0.1:8080/res/foo​​

    ​,可以通路到資源伺服器的資源。

另一種測試

關閉浏覽器重新打開,浏覽器通路​

​http://127.0.0.1:8080/res/foo​

​,你看看會發生什麼?

總結

通過OAuth2用戶端、Spring Cloud Gateway、OAuth2授權伺服器、OAuth2資源伺服器的關聯,你會發現授權碼模式也可以實作完整的微服務認證授權,而且比密碼模式更加安全。後續Id Server實作了聯合登入之後,其它第三方登入也可以無縫內建進來。多多關注,更多先進的黑科技等着你。