一、前置准备
- 已部署好 Keycloak(参考之前的容器部署方式),并完成基础配置:
- 创建一个 Realm(例如:
my-realm) - 创建一个 Client(例如:
my-spring-app),Client Protocol 选择openid-connect,Access Type 选择confidential,Valid Redirect URIs 填写http://localhost:8081/*(Spring Boot 应用端口) - 记录 Client 的
Client ID和Client Secret(在 Client 的Credentials标签页) - 创建一个测试用户(例如:
test-user,设置密码)
- 创建一个 Realm(例如:
- Spring Boot 应用(2.7.x/3.x 均可,下文以 3.2.x 为例)
二、核心集成步骤(Spring Boot + Keycloak)
1. 添加 Maven 依赖
在pom.xml中引入 Keycloak 与 Spring Security 集成的核心依赖:
xml
<!-- Spring Boot Starter Security(核心) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <!-- Keycloak Spring Boot Starter(简化集成) --> <dependency> <groupId>org.keycloak</groupId> <artifactId>keycloak-spring-boot-starter</artifactId> <version>23.0.7</version> <!-- 与Keycloak服务版本保持一致 --> </dependency> <!-- Spring Boot Starter Web(用于编写测试接口) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>2. 配置 application.yml
在src/main/resources/application.yml中配置 Keycloak 连接信息和认证规则:
yaml
server: port: 8081 # Spring Boot应用端口 keycloak: # Keycloak服务地址 auth-server-url: http://localhost:8080/realms/my-realm # 对应Keycloak中创建的Client ID resource: my-spring-app # 对应Keycloak中Client的Secret(confidential类型需要) credentials: secret: <你的Client Secret> # 开启Bearer Token认证(API接口常用) bearer-only: true # 所属Realm realm: my-realm # 关闭自动创建用户(生产环境建议开启) use-resource-role-mappings: true spring: security: # 禁用默认的CSRF(仅测试用,生产环境根据场景决定) csrf: enabled: false3. 编写 Spring Security 配置类
创建SecurityConfig.java,配置认证规则和 Keycloak 集成:
java
运行
import org.keycloak.adapters.springsecurity.KeycloakConfiguration; import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider; import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper; import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy; import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy; /** * Keycloak安全配置类 */ @KeycloakConfiguration public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter { // 注入Keycloak认证提供者 @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) { KeycloakAuthenticationProvider provider = new KeycloakAuthenticationProvider(); // 统一角色前缀(Keycloak的Role默认不带ROLE_,Spring Security需要) provider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper()); auth.authenticationProvider(provider); } // 配置Session策略(无状态API用Null) @Bean @Override protected SessionAuthenticationStrategy sessionAuthenticationStrategy() { return new NullAuthenticatedSessionStrategy(); } // 配置HTTP请求的认证规则 @Override protected void configure(HttpSecurity http) throws Exception { super.configure(http); http // 配置接口访问规则 .authorizeHttpRequests() // 公开接口(无需认证) .requestMatchers("/public/**").permitAll() // 需要指定角色的接口(Keycloak中给用户分配的Role) .requestMatchers("/admin/**").hasRole("ADMIN") // 其他所有接口需要认证 .anyRequest().authenticated() .and() // 启用Bearer Token认证(API接口常用) .oauth2ResourceServer() .jwt(); } }4. 编写测试接口
创建TestController.java,验证认证效果:
java
运行
import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * 测试接口 */ @RestController @RequestMapping public class TestController { // 公开接口(无需认证) @GetMapping("/public/hello") public String publicHello() { return "Hello, Public!"; } // 需认证的接口(任意登录用户) @GetMapping("/private/hello") public String privateHello(Authentication authentication) { // 获取当前登录用户信息 String username = authentication.getName(); return "Hello, " + username + "! (Private)"; } // 需ADMIN角色的接口 @GetMapping("/admin/hello") public String adminHello(Authentication authentication) { String username = authentication.getName(); return "Hello, " + username + "! (Admin)"; } }5. 编写 Keycloak 配置 Bean(可选,Spring Boot 3.x 需补充)
创建KeycloakConfig.java,确保 Keycloak 配置生效:
java
运行
import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * Keycloak配置解析器 */ @Configuration public class KeycloakConfig { // 启用Spring Boot配置文件中的Keycloak配置 @Bean public KeycloakSpringBootConfigResolver keycloakConfigResolver() { return new KeycloakSpringBootConfigResolver(); } }三、测试验证
1. 获取 Keycloak 的 Access Token
通过 Keycloak 的 Token 接口获取测试用户的 Token(Postman/curl 均可):
bash
运行
# curl命令获取Token curl -X POST \ http://localhost:8080/realms/my-realm/protocol/openid-connect/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=test-user" \ -d "password=<test-user的密码>" \ -d "grant_type=password" \ -d "client_id=my-spring-app" \ -d "client_secret=<你的Client Secret>"返回结果中会包含access_token(JWT 格式),复制该值。
2. 测试接口访问
- 公开接口:直接访问
http://localhost:8081/public/hello,返回Hello, Public!(无需 Token)。 - 私有接口:在请求头中添加
Authorization: Bearer <access_token>,访问http://localhost:8081/private/hello,返回当前用户名。 - Admin 接口:如果测试用户没有 ADMIN 角色,访问
http://localhost:8081/admin/hello会返回 403 Forbidden;给用户分配 ADMIN 角色后,即可正常访问。
四、核心原理说明
认证流程:
- 客户端(前端 / Postman)向 Keycloak 请求 Token → Keycloak 验证用户身份后返回 JWT 格式的 Access Token。
- 客户端携带 Token 调用 Spring Boot 接口 → Spring Security 通过 Keycloak 适配器验证 Token 的合法性(签名、有效期、Realm/Client 匹配)。
- 验证通过后,解析 Token 中的用户信息和角色,根据配置的访问规则判断是否允许访问接口。
关键注意点:
- Token 格式:Keycloak 默认返回 JWT 格式的 Token,Spring Security 通过 JWT 解析验证。
- 角色映射:Keycloak 的 Role 名称默认不带
ROLE_,Spring Security 需要通过SimpleAuthorityMapper补充前缀(或修改 Keycloak 配置)。 - 环境适配:生产环境中,Keycloak 的
auth-server-url需配置为公网可访问的地址,且建议开启 HTTPS。
总结
- 核心依赖:Spring Boot 集成 Keycloak 需引入
keycloak-spring-boot-starter和spring-boot-starter-security。 - 配置核心:在
application.yml中填写 Keycloak 的服务地址、Client ID/Secret、Realm 等信息。 - 认证规则:通过 Spring Security 配置类定义接口的访问权限(公开 / 需认证 / 需指定角色)。
- 测试方式:先从 Keycloak 获取 Access Token,再携带 Token 调用接口验证认证效果。