1. 概述
Keycloak 是一個免費且開源的身份和訪問管理程序,經常被用於我們今天的軟件堆棧中。在測試階段,禁用其使用可能有助於我們專注於業務測試。我們可能在測試環境中沒有 Keycloak 服務器。
在本教程中,我們將禁用 Keycloak 啓動器中配置的設置。我們還將研究在項目啓用 Spring Security 時如何修改它。
2. 取消啓用 Keycloak 在非 Spring Security 環境中
我們首先來看一下在不使用 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 中:
<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 添加一個檢索 User 的代碼:
@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 適配器實現了 Spring 自動配置 的 Keycloak 安全功能。自動配置依賴於類在類路徑中存在或屬性值的存在。特別是,@ConditionalOnProperty 註解對於這種特定需求非常有用。
要禁用 Keycloak 安全功能,我們需要告知適配器不要加載相應的配置。我們可以通過如下方式設置屬性:
keycloak.enabled=false
如果在再次運行測試之前,我們再次運行測試,它將成功,而無需進行任何身份驗證。
3. 取消啓用 Keycloak 在 Spring Security 環境中的使用
我們經常將 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。
我們可以使用 profiles 來告訴 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 {
// ...
}
作為結果,Spring 僅在 keycloak.enable 屬性的值為 true 時才啓用 Keycloak 配置。 如果屬性丟失,matchIfMissing 將默認啓用它。
由於我們正在使用 Spring Security starter,僅僅禁用我們的 Spring Security 配置是不夠的。 事實上,遵循 Spring 的默認配置原則,starter 將創建一個默認的安全層。
讓我們創建一個配置類來禁用它:
@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。