1. 概述
Keycloak 是一个免费且开源的身份和访问管理程序,常常在当今的软件栈中使用。在测试阶段,我们可能会希望禁用它的使用,以便专注于业务测试。测试环境中可能也没有Keycloak服务器。
在这个教程中,我们将移除由Keycloak启动器设置的配置,还会探讨在项目中启用Keycloak时如何修改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令牌。因此,让我们将其添加到pom.xml:
<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(name = "userId") 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
没有提供任何身份验证,或者Keycloak服务器不可用。
Keycloak适配器实现了Keycloak安全的Spring自动配置。自动配置依赖于类路径中的类或属性值。特别是,对于这种特定需求,[@ConditionalOnProperty注解]非常有用。
为了禁用Keycloak安全,我们需要告知适配器不应加载相应的配置。我们可以这样做,如下所示:
keycloak.enabled=false
再次运行测试,它现在会在没有任何身份验证的情况下成功。
3. 在Spring Security环境中禁用Keycloak
我们经常使用Keycloak与Spring Security配合。在这种情况下,仅仅禁用Keycloak配置是不够的,还需要修改Spring Security配置以允许匿名请求到达控制器。
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(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth -> auth.anyRequest()
.permitAll())
.oauth2Login(Customizer.withDefaults())
.oauth2ResourceServer(httpSecurityOAuth2ResourceServerConfigurer ->
httpSecurityOAuth2ResourceServerConfigurer.jwt(Customizer.withDefaults()));
return http.build();
}
}
在这里,我们配置Spring Security只允许已认证用户的请求。
3.2. 禁用Keycloak
除了像之前那样禁用Keycloak外,现在我们还需要禁用Spring Security。
我们可以使用profile告诉Spring在测试时是否激活Keycloak配置:
@Configuration
@EnableWebSecurity
@Profile("tests")
public class KeycloakSecurityConfig {
// ...
}
然而,更优雅的方法是重用keycloak.enable
属性,类似于Keycloak适配器:
@Configuration
@EnableWebSecurity
@ConditionalOnProperty(name = "keycloak.enabled", havingValue = "true", matchIfMissing = true)
public class KeycloakSecurityConfig {
// ...
}
因此,如果keycloak.enable
属性为true
,Spring才会启用Keycloak配置。如果属性缺失,matchIfMissing
默认启用它。
由于我们使用了Spring Security启动器,仅仅禁用我们的Spring Security配置是不够的。实际上,遵循Spring的主观默认配置原则,启动器会创建一个默认的安全层。
让我们创建一个配置类来禁用它:
@Configuration
@ConditionalOnProperty(name = "keycloak.enabled", havingValue = "false")
public class DisableSecurityConfiguration {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(request -> request.anyRequest()
.permitAll());
return http.build();
}
}
我们仍然使用keycloak.enable
属性,但这次Spring会在其值为false
时启用配置。
4. 总结
在这篇文章中,我们探讨了如何在Spring环境中禁用Keycloak安全,无论是否使用Spring Security。
如往常一样,本文中使用的所有代码示例可以在GitHub上找到。