Keycloak簡單幾步實現對Spring Boot應用的權限控制

我們在上一篇初步嘗試了keycloak,手動建立了一個名爲felord.cnrealm並在該realm下建了一個名爲felord的用戶。今天就來嘗試一下對應的Spring Boot Adapter,來看看keycloak是如何保護Spring Boot應用的。

客戶端

相信不少同學用過微信開放平臺、螞蟻開放平臺。首先我們需要在這些開放平臺上註冊一個客戶端以獲取一套類似用戶名和密碼的憑證。有的叫appidsecret;有的叫clientidsecret,都是一個意思。其實keycloak也差不多,也需要在對應的realm中註冊一個客戶端。下圖不僅僅清晰地說明了keycloakMasterrealm和自定義realm的關係,還說明了在一個realm中用戶和客戶端的關係。

Realm、client、user關係圖

我們需要在felord.cn這個realm中建立一個客戶端:

在realm中創建客戶端

創建完畢後你會發現felord.cn的客戶端又多了一個:

realm的客戶端列表

你可以通過http://localhost:8011/auth/realms/felord.cn/account/來登錄創建的用戶。

然後我們對客戶端spring-boot-client進行編輯配置:

填寫重定向URL

爲了測試,這裏我只填寫了設置選項卡中唯一的必填項有效的重定向URI,這個選項的意思就是客戶端springboot-client的所有API都會收到權限管控。

角色

基於角色的權限控制是目前主流的權限控制思想,keycloak也採取了這種方式。我們需要建立一個角色並授予上一篇文章中建立的用戶felord。我們來創建一個簡單的角色:

在keycloak中創建角色

keycloak的角色功能非常強大,在後面的系列文章中胖哥會和大家深入學習這個概念。

角色映射給用戶

然後我們把上面創建的角色base_user賦予用戶felord:

給realm中的用戶賦予角色

到這裏用戶、角色、角色映射都搞定了,就剩下在客戶端上定義資源了。

獲取和刷新JWT

我們可以通過下面這個方式獲取用戶登錄的JWT對:

POST /auth/realms/felord.cn/protocol/openid-connect/token HTTP/1.1
Host: localhost:8011
Content-Type: application/x-www-form-urlencoded

client_id=springboot-client&username=felord&password=123456&grant_type=password

會得到:

{
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiS 省略",
    "expires_in": 300,
    "refresh_expires_in": 1800,
    "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAi 省略",
    "token_type": "Bearer",
    "not-before-policy": 0,
    "session_state": "2fc7e289-c86f-4f6f-b4d3-1183a9518acc",
    "scope": "profile email"
}

刷新Token只需要把refresh_token帶上,把grant_type改爲refresh_token就可以刷新Token對了,下面是請求刷新的報文:

POST /auth/realms/felord.cn/protocol/openid-connect/token HTTP/1.1
Host: localhost:8011
Content-Type: application/x-www-form-urlencoded

client_id=springboot-client&grant_type=refresh_token&refresh_token=eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJlYWE2MThhMC05Y2UzLTQxZWMtOTZjYy04MGQ5ODVkZjJjMTIifQ.eyJleHAiOjE2MjU3NjI4ODYsImlhdCI6MTYyNTc2MTA4NiwianRpIjoiZjc2MjVmZmEtZWU3YS00MjZmLWIwYmQtOTM3MmZiM2Q4NDA5IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDExL2F1dGgvcmVhbG1zL2ZlbG9yZC5jbiIsImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODAxMS9hdXRoL3JlYWxtcy9mZWxvcmQuY24iLCJzdWIiOiI0YzFmNWRiNS04MjU0LTQ4ZDMtYTRkYS0wY2FhZTMyOTk0OTAiLCJ0eXAiOiJSZWZyZXNoIiwiYXpwIjoic3ByaW5nYm9vdC1jbGllbnQiLCJzZXNzaW9uX3N0YXRlIjoiZDU2NmU0ODMtYzc5MS00OTliLTg2M2ItODczY2YyNjMwYWFmIiwic2NvcGUiOiJwcm9maWxlIGVtYWlsIn0.P4vWwyfGubSt182P-vcyMdKvJfvwKYr1nUlOYBWzQks

注意:兩個請求的 content-type都是application/x-www-form-urlencoded

Spring Boot客戶端

建一個很傳統的Spring Boot應用,別忘了帶上Spring MVC模塊,然後加入keycloakstarter:

        <dependency>
            <groupId>org.keycloak</groupId>
            <artifactId>keycloak-spring-boot-starter</artifactId>
            <version>14.0.0</version>
        </dependency>

當前keycloak版本是14.0.0

然後隨便編寫一個Spring MVC接口:

/**
 * @author felord.cn
 * @since 2021/7/7 17:05
 */
@RestController
@RequestMapping("/foo")
public class FooController {

    @GetMapping("/bar")
    public String bar(){
        return "felord.cn";
    }

}

接下來,我們聲明定義只有felord.cnrealm中包含base_user角色的用戶才能訪問/foo/bar接口。那麼定義在哪兒呢?我們先在spring boot中的application.yml中靜態定義,後續會實現動態控制。配置如下:

keycloak:
# 聲明客戶端所在的realm
  realm: felord.cn
# keycloak授權服務器的地址
  auth-server-url: http://localhost:8011/auth
# 客戶端名稱
  resource: springboot-client
# 聲明這是一個公開的客戶端,否則不能在keycloak外部環境使用,會403
  public-client: true
# 這裏就是配置客戶端的安全約束,就是那些角色映射那些資源
  security-constraints:
# 角色和資源的映射關係。下面是多對多的配置方式 ,這裏只配置base_user才能訪問 /foo/bar
    - auth-roles:
        - base_user
      security-collections:
        - patterns:
            - '/foo/bar'

然後啓動Spring Boot應用並在瀏覽器中調用http://localhost:8080/foo/bar,你會發現瀏覽器會跳轉到下面這個地址:

http://localhost:8011/auth/realms/felord.cn/protocol/openid-connect/auth?response_type=code&client_id=springboot-client&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Ffoo%2Fbar&state=20e0958d-a7a9-422a-881f-cbd8f25d7842&login=true&scope=openid

OIDC認證授權登錄

走的是基於OIDC(OAuth 2.0的增強版)的認證授權模式。只有你正確填寫了用戶名和密碼才能得到/foo/bar的正確響應。

總結

請注意:這是系列文章,請點擊文章開頭的#keycloak查看已有章節。

我們僅僅進行了一些配置就實現了OIDC認證授權,保護了Spring Boot中的接口,這真是太簡單了。不過看了這一篇文章後你會有不少疑問,這是因爲你不太瞭解OIDC協議。這個協議非常重要,大廠都在使用這個協議。下一篇會針對這個協議來給你補補課。本文的DEMO已經上傳到Git,你可以關注公衆號:碼農小胖哥 回覆 keycloak3獲取DEMO。多多點贊、再看、轉發、評論、有飯恰纔是胖哥創作分享的動力。

關注公衆號:Felordcn獲取更多資訊

個人博客:https://felord.cn

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