51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

在 Spring Boot 中禁用 Keycloak Security

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

赞(1)
未经允许不得转载:工具盒子 » 在 Spring Boot 中禁用 Keycloak Security