1. 概述
Keycloak 是一個免費且開源的身份和訪問管理程序,經常被用於我們今天的軟件堆棧中。在測試階段,禁用其使用可能有助於我們專注於業務測試。我們可能在測試環境中也沒有 Keycloak 服務器。
在本教程中,我們將禁用 Keycloak starter 中配置的設置。我們還將研究在項目啓用 Spring Security 時如何修改它。
2. 在非 Spring Security 環境中禁用 Keycloak
我們將首先探討如何在不使用 Spring Security 的應用程序中禁用 Keycloak。
2.1. 應用配置
讓我們首先添加 <em ><a href="https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-oauth2-client">spring-boot-starter-oauth2-client</a></em> 依賴項到我們的項目:
<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. 在 Spring Security 環境中禁用 Keycloak
我們經常將 Keycloak 與 Spring Security 結合使用。 在這種情況下,僅僅禁用 Keycloak 配置是不夠的,我們需要修改 Spring Security 配置,以允許匿名請求到達控制器。
3.1. 應用設置
讓我們首先將 <a href="https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-security">spring-boot-starter-security</a> 依賴添加到我們的項目中:
<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
正如我們之前所做的那樣,現在我們也需要禁用 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 的 Opinionated 默認配置原則,該 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。