自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

全面解析 Keycloak:如何優(yōu)雅集成到 Spring Boot 3 應(yīng)用中?

開發(fā) 前端
本文詳細(xì)介紹了如何通過 Keycloak 生成 JWT 令牌,并將其與 Spring Boot 集成,實(shí)現(xiàn)基于角色的權(quán)限控制。通過配置 Keycloak 生成令牌,設(shè)置 Spring Security 的 JWT 解析邏輯,以及定義基于角色的訪問控制,我們構(gòu)建了一個(gè)安全、高效的認(rèn)證與授權(quán)機(jī)制。

Keycloak 是一種開源身份和訪問管理工具,可以幫助用戶以最小的努力為應(yīng)用程序添加身份驗(yàn)證功能。

Keycloak 的一些主要特性

  1. 單點(diǎn)登錄與單點(diǎn)注銷 (Single Sign-On and Single Sign-Out):用戶不需要為不同的應(yīng)用程序設(shè)置不同的登錄賬號(hào)。
  2. 社交登錄與身份代理 (Social Login and Identity Brokering):支持使用 Google、Facebook 等社交登錄功能,并可以輕松配置已有的身份提供商。
  3. 用戶聯(lián)合 (User Federation):內(nèi)置支持連接現(xiàn)有的 LDAP 和 Active Directory 服務(wù)器。
  4. 管理控制臺(tái) (Admin Console)。
  5. 授權(quán)服務(wù) (Authorisation Services):幫助管理所有客戶服務(wù)的權(quán)限,支持細(xì)粒度的權(quán)限控制。

了解 Keycloak 的幾個(gè)重要術(shù)語

  1. Realm (領(lǐng)域):一個(gè)安全域,用于管理用戶、應(yīng)用程序、組和權(quán)限,便于資源、權(quán)限和配置的隔離與組織。
  2. Client (客戶端):能夠請(qǐng)求用戶身份驗(yàn)證的應(yīng)用程序或服務(wù)。
  3. Client Scopes (客戶端范圍):多個(gè)客戶端之間共享的通用規(guī)則和權(quán)限。
  4. Realm Roles (領(lǐng)域角色):在當(dāng)前領(lǐng)域范圍內(nèi)定義的角色。

Keycloak 入門

我們可以通過 Docker 啟動(dòng) Keycloak 服務(wù)器。使用以下命令啟動(dòng) Keycloak 服務(wù)器:

docker run -p8081:8080 -eKEYCLOAK_ADMIN=admin -eKEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:25.0.4 start-dev

服務(wù)器將啟動(dòng)在 8081 端口。默認(rèn)用戶名和密碼是 admin??梢酝ㄟ^瀏覽器訪問 localhost:8081/admin。

以下是管理控制臺(tái)的界面:

圖片圖片

創(chuàng)建領(lǐng)域 (Realm)

首先,我們需要?jiǎng)?chuàng)建一個(gè)領(lǐng)域來管理用戶和應(yīng)用程序。創(chuàng)建領(lǐng)域的方法如下:

  1. 點(diǎn)擊左側(cè)的 Realm。
  2. 然后點(diǎn)擊 Create。

圖片

創(chuàng)建用戶

創(chuàng)建用戶的步驟如下:

  1. 點(diǎn)擊左側(cè)的 Users。
  2. 點(diǎn)擊 Add User 按鈕。接著會(huì)出現(xiàn)一個(gè)如下的表單:

圖片

添加客戶端 (Client)

可以按以下步驟添加我們的應(yīng)用程序或服務(wù):

  1. 點(diǎn)擊左側(cè)的 Clients。
  2. 點(diǎn)擊 Create Client。
  3. 接下來會(huì)出現(xiàn)一個(gè)表單,如下圖 Screenshot_1 所示。在連接 Spring Boot 應(yīng)用程序和 Keycloak 時(shí),ClientId 非常重要。
  4. 在 Root URL 中填寫 Spring Boot 應(yīng)用的基礎(chǔ) URL (參考下圖 Screenshot_2)。
  5. 完成后的表單看起來如 Screenshot_3 所示。

圖片圖片

圖片圖片

圖片圖片

創(chuàng)建客戶端后,可以為該客戶端創(chuàng)建 Roles (角色)。

這些角色可以分配給用戶,用戶將根據(jù)權(quán)限訪問不同的端點(diǎn)。

假設(shè)我們創(chuàng)建了兩個(gè)用戶 testadmin 和 testuser,同時(shí)創(chuàng)建了兩個(gè)角色 client_admin 和 client_user。

圖片圖片

如何使用 Keycloak 生成 JWT Token?

您需要通過 HTTP POST 方法向以下 URL 發(fā)送請(qǐng)求:http://localhost:8081/realms/master/protocol/openid-connect/token (假設(shè) Keycloak 服務(wù)器運(yùn)行在 localhost:8081)

請(qǐng)求體

請(qǐng)求體應(yīng)為 x-www-form-urlencoded 類型,并包含以下參數(shù):

  • grant_type(文本)— 表示請(qǐng)求所用的授權(quán)類型。
  • client_id(文本)— 請(qǐng)求的客戶端標(biāo)識(shí)符。
  • username(文本)— 用于身份驗(yàn)證的用戶名。
  • password(文本)— 用于身份驗(yàn)證的密碼。

示例請(qǐng)求體

grant_type:password
client_id:keycloak-integration-app
username:testuser
password:testuser

如果請(qǐng)求成功,API 將返回一個(gè)包含 access token 的 JSON 響應(yīng)。此 Token 可用于調(diào)用我們 Spring Boot 應(yīng)用的各種接口。

將 Keycloak 集成到 Spring Boot 中

創(chuàng)建一個(gè)簡單的 Spring Boot 應(yīng)用,并添加以下依賴

  1. Spring Web
  2. Spring Security
  3. Lombok
  4. OAuth2 Authorization Server
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

創(chuàng)建 SecurityConfig 類:

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@RequiredArgsConstructor
public class SecurityConfig {


    private final JwtConvertor jwtConvertor;


    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {


        httpSecurity
                .csrf(csrf -> csrf.disable())
                .authorizeHttpRequests(auth -> auth.anyRequest().authenticated());


        httpSecurity
                .oauth2ResourceServer(oauth2 -> oauth2
                        .jwt(jwt -> jwt
                                .jwtAuthenticationConverter(jwtConvertor)));


        httpSecurity
                .sessionManagement(sessMngmt ->
                        sessMngmt.sessionCreationPolicy(SessionCreationPolicy.STATELESS));


        return httpSecurity.build();
    }
}

創(chuàng)建 JwtConvertor 類以提取角色。

以下是解碼 JWT 時(shí)的角色 JSON 示例:

"resource_access": {
"keycloak-integration-app": {
"roles": [
"client_admin"
]
},
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
}
}

為了獲取角色,我們需要?jiǎng)?chuàng)建一個(gè)轉(zhuǎn)換器類:

public class JwtConvertor implements Converter<Jwt, AbstractAuthenticationToken> {


    private final JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter =
            new JwtGrantedAuthoritiesConverter();


    private String principleAttribute;


    @Override
    public AbstractAuthenticationToken convert(Jwt source) {
        Collection<GrantedAuthority> authorities = Stream.concat(
                jwtGrantedAuthoritiesConverter.convert(source).stream(),
                extractResourceRoles(source).stream()
        ).collect(Collectors.toSet());


        return new JwtAuthenticationToken(
                source,
                authorities,
                getPrincipleClaimName(source)
        );
    }


    private String getPrincipleClaimName(Jwt source) {
        String claimName = JwtClaimNames.SUB;
        if (principleAttribute != null) {
            claimName = principleAttribute;
        }
        return source.getClaim(claimName);
    }


    private Collection<? extends GrantedAuthority> extractResourceRoles(Jwt jwt) {
        Map<String, Object> resourceAccess;
        Map<String, Object> resource;
        Collection<String> resourceRoles;
        if (jwt.getClaim("resource_access") == null) {
            return Set.of();
        }
        resourceAccess = jwt.getClaim("resource_access");


        if (resourceAccess.get("keycloak-integration-app") == null) {
            return Set.of();
        }
        resource = (Map<String, Object>) resourceAccess.get("keycloak-integration-app");


        resourceRoles = (Collection<String>) resource.get("roles");
        return resourceRoles
                .stream()
                .map(role -> new SimpleGrantedAuthority("ROLE_" + role))
                .collect(Collectors.toSet());
    }
}

在 application.yml 中添加配置:

spring:
application:
name: keycloak-integration
security:
oauth2:
resourceserver:
jwt:
issuer-uri: sample_issuer_uri
jwk-set-uri: sample_cert

可以通過以下 GET API 獲取 issuer-uri 和 jwk-set-uri:

http://localhost:8081/realms/{realm_name}/.well-known/openid-configuration

## 將 {realm_name} 替換為您的 Realm 名稱

創(chuàng)建 REST Controller

@RestController
@RequestMapping(value = "/data")
public class DataController {


    @GetMapping(value = "/user")
    @PreAuthorize("hasRole('client_user')")
    public String userApi(){
        return "I am a user";
    }


    @GetMapping(value = "/admin")
    @PreAuthorize("hasRole('client_admin')")
    public String adminApi(){
        return "I am an Admin";
    }
}

我們的集成現(xiàn)在已經(jīng)完成,可以通過生成 Keycloak 的 access token 來訪問 API(如上所述)。

使用 testuser 的 JWT 調(diào)用 /data/admin 接口時(shí),會(huì)返回 403,但可以正常訪問 /data/user。對(duì)于 testadmin 用戶也是如此。

資源

  1. Keycloak 入門文檔請(qǐng)參閱 https://www.keycloak.org/guides#getting-started。
  2. JWT 官網(wǎng)https://jwt.io/

總結(jié)

本文詳細(xì)介紹了如何通過 Keycloak 生成 JWT 令牌,并將其與 Spring Boot 集成,實(shí)現(xiàn)基于角色的權(quán)限控制。

通過配置 Keycloak 生成令牌,設(shè)置 Spring Security 的 JWT 解析邏輯,以及定義基于角色的訪問控制,我們構(gòu)建了一個(gè)安全、高效的認(rèn)證與授權(quán)機(jī)制。

這套流程為應(yīng)用的安全性和擴(kuò)展性提供了保障,適用于多角色分布式系統(tǒng)開發(fā)。

責(zé)任編輯:武曉燕 來源: 路條編程
相關(guān)推薦

2021-07-09 06:48:29

Spring Boot應(yīng)用Keycloak

2021-01-07 14:06:30

Spring BootJUnit5Java

2025-01-02 11:20:47

2020-07-14 11:00:12

Spring BootRedisJava

2022-10-26 07:14:25

Spring 6Spring業(yè)務(wù)

2021-08-26 11:00:54

Spring BootJUnit5Java

2024-12-06 09:27:28

2020-09-02 17:28:26

Spring Boot Redis集成

2024-09-27 12:27:31

2024-10-11 11:46:40

2023-11-01 08:58:10

2021-03-09 13:18:53

加密解密參數(shù)

2022-06-04 12:25:10

解密加密過濾器

2025-03-28 08:34:34

2025-02-07 09:11:04

JSON對(duì)象策略

2024-01-16 08:17:29

Mybatis驗(yàn)證業(yè)務(wù)

2021-12-28 11:13:05

安全認(rèn)證 Spring Boot

2024-10-08 09:27:04

SpringRESTfulAPI

2022-05-12 11:38:26

Java日志Slf4j

2024-11-06 11:33:09

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)