Spring Boot - 如何禁用Keycloak?

15
我有一个集成了Keycloak的Spring Boot项目。现在,出于测试目的,我想禁用Keycloak。
我尝试通过在application.properties中添加keycloak.enabled=false来实现,就像Keycloak documentation中提到的那样,但它没有起作用。
那么我该如何禁用它呢?

你尝试过从Maven或Gradle构建文件的依赖项部分中删除keycloak-spring-boot-starter吗? - Alexey Sviridov
2
不,我实际上想要禁用它,而不是删除keycloak依赖项。 - Charlie
你解决了这个问题吗?我想在Spring Boot控制器测试中禁用它,但是这个帖子中的解决方案都没有起作用。 - Justinas Jakavonis
我刚刚在下面发布了我的解决方案,请看一下。 - Charlie
5个回答

14

更新2022年

请参考Baeldung上这篇出色的指南


对于可能遇到相同问题的人,以下是我所做的操作。

我没有禁用Keycloak,但为测试目的创建了一个独立的Keycloak配置文件。

这是我的配置文件:

@Profile("test")
@Configuration
@EnableWebSecurity
public class SecurityTestConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/**").permitAll();
        http.headers().frameOptions().disable();
        http.csrf().disable();

    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/**");
    }

    @Bean
    @Scope(scopeName = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public AccessToken accessToken() {
        AccessToken accessToken = new AccessToken();
        accessToken.setSubject("abc");
        accessToken.setName("Tester");

        return accessToken;

    }

}

请注意,仅在测试环境中使用此配置非常重要,因此我已将其注释为@Profile("test")。我还添加了一个AccessToken bean,因为我的应用程序中的某些审计功能依赖于它。


5

这应该可以工作,但基于对此问题的最后一条评论(请参见jira工单),似乎并不是这样。

根据描述,您可以在 application.properties 中添加以下内容来排除 keycloak 的 spring boot 自动配置:spring.autoconfigure.exclude=org.keycloak.adapters.springboot.KeycloakSpringBootConfiguration


3
如果您同时启用了Spring Security,enable标志将不起作用,它仅在单独使用Spring Boot适配器时才有效。我们有一张支持在使用Spring Security时也能使用该标志的票据。 - Sébastien Blanc
现在要排除的类名是 KeycloakAutoConfiguration,适用于 Spring Boot 2.5.6 + Keycloak 16.1.0(请参见下面我的答案)。 - Rhubarb

3

您需要排除 Keycloak 自动配置。为此,只需将以下条目添加到相关的 Spring 配置文件中,即在您的情况下是 application.properties。

spring.autoconfigure.exclude = org.keycloak.adapters.springboot.KeycloakAutoConfiguration

2

我的解决方法:

1. 创建一个自定义过滤器并将其添加到(Spring)安全链中的早期位置。
2. 在application.yml中创建一个标志(securityEnabled)
3. 在Custom-Filter中查询该标志。如果为“true”,则通过调用chain.doFilter()继续下一个过滤器。如果为“false”,则创建一个虚拟的Keycloak账户,设置所需的角色,并将其设置为上下文。
4. 顺便提一下,这些角色也被外包给了application.yml
5. 跳过安全链中的其余过滤器(因此不执行keycloak相关操作并发生相应的授权)

详细说明:

1. 自定义过滤器的类

public class CustomFilter extends OncePerRequestFilter {

  @Value("${securityEnabled}")
  private boolean securityEnabled;

  @Value("${grantedRoles}")
  private String[] grantedRoles;

  @Override
  public void doFilterInternal(HttpServletRequest req, HttpServletResponse res,
                       FilterChain chain) throws IOException, ServletException {

      if (!securityEnabled){
          // Read roles from application.yml
          Set<String> roles = Arrays.stream(grantedRoles)
                  .collect(Collectors.toCollection(HashSet::new));
          // Dummy Keycloak-Account
          RefreshableKeycloakSecurityContext session = new RefreshableKeycloakSecurityContext(null, null, null, null, null, null, null);
          final KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = new KeycloakPrincipal<>("Dummy_Principal", session);
          final KeycloakAccount account = new SimpleKeycloakAccount(principal, roles, principal.getKeycloakSecurityContext());
          // Dummy Security Context
          SecurityContext context = SecurityContextHolder.createEmptyContext();
          context.setAuthentication(new KeycloakAuthenticationToken(account, false));
          SecurityContextHolder.setContext(context);

          // Skip the rest of the filters
          req.getRequestDispatcher(req.getServletPath()).forward(req, res);
      }

      chain.doFilter(req, res);
  }
}

2. 在Spring-Security的http配置中插入自定义过滤器。
protected void configure(HttpSecurity http) throws Exception {
    super.configure(http);
    http
            .cors()
            .and()
            .csrf()
            .disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .sessionAuthenticationStrategy(sessionAuthenticationStrategy())
            .and()
            .addFilterAfter(CustomFilter(), CsrfFilter.class)
            .authorizeRequests()
            .anyRequest().permitAll();
}

请看配置 Keycloak 后的默认过滤器链:

过滤器链

很明显,将自定义过滤器插入到第 5 个位置可以避免整个 Keycloak 魔法。
我使用了这个解决方法来打败方法安全和 @Secured 注释。

那么,您如何重新启用Keycloak?通过注释过滤器吗? - Charlie
通过在application.yml中设置标志securityEnabled = true。然后过滤器中的if语句将被跳过。 - Twelve
什么是 ".sessionAuthenticationStrategy(sessionAuthenticationStrategy())"?你如何定义方法sessionAuthenticationStrategy()? - Asu
我无法让这种方法起作用。即使过滤器已经在正确的链路上注册,我的自定义过滤器的“doFilterInternal”方法也从未被调用。尝试直接实现Filter或扩展GenericFilterBean,但是“doFilter”从未被调用... - Asu

0

针对Spring Boot 2.5.6和Keycloak 16.1.0的更新答案如下:

在您的application.properties文件中设置以下内容:

spring.autoconfigure.exclude=org.keycloak.adapters.springboot.KeycloakAutoConfiguration

(自动配置类名称与早期答案不同)

Keycloak适配器依赖项还会带入标准的Spring安全自动配置,因此如果您想要同时禁用两者,请使用以下内容:

spring.autoconfigure.exclude=org.keycloak.adapters.springboot.KeycloakAutoConfiguration,org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接