You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将Keycloak部署在Spring Cloud Gateway后禁用HTTP Basic Auth的问题

问题描述

我希望将Keycloak部署在Spring Cloud Gateway之后,同时将其用作OIDC提供商。目前已成功放行Keycloak的/auth及/auth/**端点,但无法禁用HTTP Basic Auth。每当访问需由Keycloak保护的其他端点时,都会弹出浏览器表单登录框。

使用的配置代码:

@Bean
@Order(1)
SecurityWebFilterChain publicEndpoints(final ServerHttpSecurity http) {
    return http.authorizeExchange(auth ->
                    auth.pathMatchers("/auth", "/auth/**").permitAll())
            .csrf(ServerHttpSecurity.CsrfSpec::disable)
            .cors(ServerHttpSecurity.CorsSpec::disable)
            .formLogin(ServerHttpSecurity.FormLoginSpec::disable)
            .headers(c -> c.frameOptions(ServerHttpSecurity.HeaderSpec.FrameOptionsSpec::disable))
            .httpBasic(basic ->
                    basic.authenticationEntryPoint(new HttpStatusServerEntryPoint(HttpStatus.UNAUTHORIZED)))
            .build();
}

@Bean
@Order(2)
SecurityWebFilterChain springSecurityFilterChain(final ServerHttpSecurity http) {
    return http.authorizeExchange(auth -> auth.anyExchange().authenticated())
            .oauth2Login(withDefaults())
            .oauth2ResourceServer((oauth2) -> oauth2.jwt(withDefaults()))
            .csrf(ServerHttpSecurity.CsrfSpec::disable)
            .cors(ServerHttpSecurity.CorsSpec::disable)
            .formLogin(ServerHttpSecurity.FormLoginSpec::disable)
            .headers(c -> c.frameOptions(ServerHttpSecurity.HeaderSpec.FrameOptionsSpec::disable))
            //.httpBasic(ServerHttpSecurity.HttpBasicSpec::disable)
            .build();

}

启动时出现的错误:

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.web.server.SecurityWebFilterChain]: Factory method 'publicEndpoints' threw exception with message: authenticationManager cannot be null
2025-03-06T15:35:01.907890843Z  at org.springframework.beans.factory.support.SimpleInstantiationStrategy.lambda$instantiate$0(SimpleInstantiationStrategy.java:199) ~[spring-beans-6.2.3.jar:6.2.3]
2025-03-06T15:35:01.907892426Z  at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiateWithFactoryMethod(SimpleInstantiationStrategy.java:88) ~[spring-beans-6.2.3.jar:6.2.3]
2025-03-06T15:35:01.907893385Z  at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:168) ~[spring-beans-6.2.3.jar:6.2.3]
2025-03-06T15:35:01.907894343Z  at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ~[spring-beans-6.2.3.jar:6.2.3]
2025-03-06T15:35:01.907895260Z  ... 39 common frames omitted

由于不想为publicEndpoints使用任何认证管理器,不清楚如何配置以禁用表单登录并使用OAuth。


解决方案
  1. 修复publicEndpoints的HTTP Basic配置
    你在publicEndpoints中配置了httpBasic并自定义认证入口点,但未提供认证管理器,这是启动报错的核心原因。既然该过滤器链仅需放行/auth相关端点、无需任何认证,直接禁用HTTP Basic即可:

    @Bean
    @Order(1)
    SecurityWebFilterChain publicEndpoints(final ServerHttpSecurity http) {
        return http
                .securityMatcher("/auth", "/auth/**") // 限定该链仅处理指定路径,避免冲突
                .authorizeExchange(auth -> auth.anyExchange().permitAll())
                .csrf(ServerHttpSecurity.CsrfSpec::disable)
                .cors(ServerHttpSecurity.CorsSpec::disable)
                .formLogin(ServerHttpSecurity.FormLoginSpec::disable)
                .httpBasic(ServerHttpSecurity.HttpBasicSpec::disable) // 直接禁用HTTP Basic
                .headers(c -> c.frameOptions(ServerHttpSecurity.HeaderSpec.FrameOptionsSpec::disable))
                .build();
    }
    

    添加securityMatcher可以让过滤器链只处理匹配的路径,提升性能同时避免和后续认证链的规则冲突。

  2. 完善springSecurityFilterChain配置
    在第二个过滤器链中,必须明确禁用HTTP Basic,避免浏览器弹出默认登录框:

    @Bean
    @Order(2)
    SecurityWebFilterChain springSecurityFilterChain(final ServerHttpSecurity http) {
        return http
                .authorizeExchange(auth -> auth.anyExchange().authenticated())
                .oauth2Login(withDefaults())
                .oauth2ResourceServer((oauth2) -> oauth2.jwt(withDefaults()))
                .csrf(ServerHttpSecurity.CsrfSpec::disable)
                .cors(ServerHttpSecurity.CorsSpec::disable)
                .formLogin(ServerHttpSecurity.FormLoginSpec::disable)
                .httpBasic(ServerHttpSecurity.HttpBasicSpec::disable) // 禁用HTTP Basic
                .headers(c -> c.frameOptions(ServerHttpSecurity.HeaderSpec.FrameOptionsSpec::disable))
                .build();
    }
    
  3. 关键说明

    • 启用httpBasic但未配置认证管理器时,Spring Security会抛出authenticationManager cannot be null错误,因为HTTP Basic依赖认证管理器验证凭证。
    • 公开端点的过滤器链不需要任何认证机制,直接禁用所有认证方式即可。
    • 多过滤器链场景下,securityMatcher是路径隔离的关键,确保每个链只处理对应范围的请求。

内容的提问来源于stack exchange,提问作者bilak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 23:53:19