在 Spring Boot 中禁用 Keycloak Security
1、概览
Keycloak 是一个开源的身份和访问管理解决方案。在测试阶段,禁用 Keycloak 可能有助于专注于业务测试。而且在测试环境中可能没有 Keycloak 服务器。
本文将带你了解如何禁用 Keycloak starter 的配置,以及如何在项目中启用 Spring Security 后如何对其进行修改。
2、在非 Spring Security 环境下禁用 Keycloak
我们首先来看看如何在不使用 Spring Security 的应用中禁用 Keycloak。
2.1、应用设置
首先,添加 spring-boot-starter-oauth2-client 依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
此外,还需要添加 spring-boot-starter-oauth2-resource-server
依赖。它将允许我们使用 Keycloak 服务器验证 JWT Token:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
接下来,在 application.properties
中添加 Keycloak 服务器的配置:
spring.security.oauth2.client.registration.keycloak.client-id=login-app
spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.keycloak.scope=openid
spring.security.oauth2.client.provider.keycloak.issuer-uri=
http://localhost:8080/realms/SpringBootKeycloak
spring.security.oauth2.client.provider.keycloak.user-name-attribute=preferred_username
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8080/realms/SpringBootKeycloak
最后,添加 UserController
来检索用户:
@RestController
@RequestMapping("/users")
public class UserController {
@GetMapping("/{userId}")
public User getCustomer(@PathVariable Long userId) {
return new User(userId, "John", "Doe");
}
}
2.2、禁用 Keycloak
现在应用已经就绪,编写一个简单的测试来获取用户:
@Test
public void givenUnauthenticated_whenGettingUser_shouldReturnUser() {
ResponseEntity<User> responseEntity = restTemplate.getForEntity("/users/1", User.class);
assertEquals(HttpStatus.SC_OK, responseEntity.getStatusCodeValue());
assertNotNull(responseEntity.getBody()
.getFirstname());
}
由于我们没有向 restTemplate
提供任何 Authentication(身份认证),或者 Keycloak 服务器不可用,因此该测试将失败。
Keycloak adapter 实现了 Keycloak Security 的 Spring 自动配置。自动配置依赖于类路径中存在的类或属性值。具体而言,@ConditionalOnProperty
注解非常适用于这个特定的需求。
要禁用 Keycloak Security,我们需要通知 adapter 不要加载相应的配置。为此,我们可以设置如下属性:
keycloak.enabled=false
再次启动测试,现在无需任何 Authentication 即可成功。
3、在 Spring Security 环境下禁用 Keycloak
我们经常将 Keycloak 与 Spring Security 结合使用。在这种情况下,仅禁用 Keycloak 配置是不够的,还需要修改 Spring Security 配置,以允许匿名请求访问 Controller。
3.1、应用设置
首先,在项目中添加 spring-boot-starter-security 依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
接下来,创建一个 SecurityFilterChain
Bean 来定义 Spring Security 所需的配置:
@Configuration
@EnableWebSecurity
public class KeycloakSecurityConfig {
@Bean
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.authorizeHttpRequests(auth -> auth.anyRequest()
.authenticated());
http.oauth2Login();
http.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
return http.build();
}
}
这里,对 Spring Security 进行配置,使其只允许来自已认证用户的请求。
3.2、禁用 Keycloak
除了像之前那样禁用 Keycloak 外,现在还需要禁用 Spring Security。
我们可以使用 profiles
来告诉 Spring 在测试期间是否激活 Keycloak 配置:
@Configuration
@EnableWebSecurity
@Profile("tests")
public class KeycloakSecurityConfig {
// ...
}
不过,更优雅的方法是重复使用 keycloak.enable
属性,类似于 Keycloak adapter:
@Configuration
@EnableWebSecurity
@ConditionalOnProperty(name = "keycloak.enabled", havingValue = "true", matchIfMissing = true)
public class KeycloakSecurityConfig {
// ...
}
因此,只有当 keycloak.enable
属性为 true
时,Spring 才会启用 Keycloak 配置。如果缺少该属性,则 matchIfMissing
会默认启用它。
由于我们使用的是 Spring Security Starter,因此仅禁用 Spring Security 配置是不够的。事实上,根据 Spring 的默认配置原则,Starter 将创建一个默认的安全层(Security Layer)。
创建一个配置类来禁用它:
@Configuration
@ConditionalOnProperty(name = "keycloak.enabled", havingValue = "false")
public class DisableSecurityConfiguration {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.authorizeRequests()
.anyRequest()
.permitAll();
return http.build();
}
}
我们仍然使用 keycloak.enable
属性,但这次 Spring 会在其值设置为 false
时启用配置。
4、总结
本文介绍了如何在 Spring 中禁用 Keycloak,包括使用 Spring Security 和未使用 Spring Security 的情况。
参考:https://www.baeldung.com/spring-keycloak-security-disable