在Spring Boot中禁用Keycloak安全

2023/05/12

1. 概述

Keycloak是一个免费的开源身份和访问管理程序,如今经常在我们的软件堆栈中使用。在测试阶段,禁用它以专注于业务测试可能很有用,我们的测试环境中也可能没有Keycloak服务器。

在本教程中,我们将禁用Keycloak starter设置的配置,并查看在我们的项目中启用Spring Security时对其进行修改。

2. 在非Spring Security环境中禁用Keycloak

我们将首先了解如何在不使用Spring Security的应用程序中禁用Keycloak。

2.1 应用设置

首先我们将keycloak-spring-boot-starter依赖项添加到我们的项目中:

<dependency>
    <groupId>org.keycloak</groupId>
    <artifactId>keycloak-spring-boot-starter</artifactId>
</dependency>

另外,我们需要添加keycloak-adapter-bom依赖带来的各种嵌入式容器的依赖:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.keycloak.bom</groupId>
            <artifactId>keycloak-adapter-bom</artifactId>
            <version>15.0.2</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

接下来,向我们的application.properties添加我们的Keycloak服务器的配置:

keycloak.auth-server-url=http://localhost:8080
keycloak.realm=SpringBootKeycloak
keycloak.resource=login-app
keycloak.public-client=true
keycloak.security-constraints[0].authRoles[0]=user
keycloak.security-constraints[0].securityCollections[0].patterns[0]=/users/*

此配置可确保对/users URL的请求只能由具有user角色的经过身份验证的用户访问

最后,让我们添加一个检索User的UserController:

@RestController
@RequestMapping("/users")
public class UserController {
    @GetMapping("/{userId}")
    public User getCustomer(@PathVariable Long userId) {
        return new User(userId, "John", "Doe");
    }
}

2.2 禁用Keycloak

现在我们的应用程序已经到位,让我们编写一个简单的测试来获取用户:

@Test
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>

接下来,我们实现WebSecurityConfigurerAdapter来定义Spring Security所需的配置,Keycloak适配器为此提供了一个抽象类和注解:

@KeycloakConfiguration
public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(keycloakAuthenticationProvider());
    }

    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new NullAuthenticatedSessionStrategy();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);

        http.csrf()
              .disable()
              .authorizeRequests()
              .anyRequest()
              .authenticated();
    }
}

在这里,我们将Spring Security配置为仅允许来自经过身份验证的用户的请求。

3.2 禁用Keycloak

除了像我们之前所做的那样禁用Keycloak之外,我们现在还需要禁用Spring Security

我们可以使用Profile来告诉Spring在我们的测试期间是否激活Keycloak配置:

@KeycloakConfiguration
@Profile("tests")
public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
    // ...
}

但是,一种更优雅的方法是重用keycloak.enable属性,类似于Keycloak适配器

@KeycloakConfiguration
@ConditionalOnProperty(name = "keycloak.enabled", havingValue = "true", matchIfMissing = true)
public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
    // ...
}

因此,只有当keycloak.enable属性为true时,Spring才会启用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()
              .disable()
              .authorizeRequests()
              .anyRequest()
              .permitAll();
        return http.build();
    }
}

我们仍在使用我们的keycloak.enable属性,但是这次如果Spring的值设置为false,则启用配置。

4. 总结

在本文中,我们介绍了如何在有或没有Spring Security的Spring环境中禁用Keycloak安全性。

与往常一样,本教程的完整源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章