1、概览 {#1概览}
Keycloak 是一个开源的身份和访问管理解决方案。在测试阶段,禁用 Keycloak 可能有助于专注于业务测试。而且在测试环境中可能没有 Keycloak 服务器。
本文将带你了解如何禁用 Keycloak starter 的配置,以及如何在项目中启用 Spring Security 后如何对其进行修改。
2、在非 Spring Security 环境下禁用 Keycloak {#2在非-spring-security-环境下禁用-keycloak}
我们首先来看看如何在不使用 Spring Security 的应用中禁用 Keycloak。
2.1、应用设置 {#21应用设置}
首先,添加 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 {#22禁用-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 {#3在-spring-security-环境下禁用-keycloak}
我们经常将 Keycloak 与 Spring Security 结合使用。在这种情况下,仅禁用 Keycloak 配置是不够的,还需要修改 Spring Security 配置,以允许匿名请求访问 Controller。
3.1、应用设置 {#31应用设置}
首先,在项目中添加 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 {#32禁用-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、总结 {#4总结}
本文介绍了如何在 Spring 中禁用 Keycloak,包括使用 Spring Security 和未使用 Spring Security 的情况。
参考:https://www.baeldung.com/spring-keycloak-security-disable