将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。
解决方案
修复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可以让过滤器链只处理匹配的路径,提升性能同时避免和后续认证链的规则冲突。完善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(); }关键说明
- 启用
httpBasic但未配置认证管理器时,Spring Security会抛出authenticationManager cannot be null错误,因为HTTP Basic依赖认证管理器验证凭证。 - 公开端点的过滤器链不需要任何认证机制,直接禁用所有认证方式即可。
- 多过滤器链场景下,
securityMatcher是路径隔离的关键,确保每个链只处理对应范围的请求。
- 启用
内容的提问来源于stack exchange,提问作者bilak
相关产品推荐
相关产品推荐

