Spring Boot Security整合Keycloak自定义登录路径报permitAll配置错误
Keycloak集成自定义登录路由问题记录
问题现状
- Keycloak集成后登录流程已验证跑通,登出功能暂未正常生效,当前核心需求是新增
/login路由映射至框架默认登录入口 - 原本预期
permitAll()配置不合法时会直接抛出语法层面错误,实际框架生成了完整的冗长安全过滤链,仅在链内零散节点拦截应用permitAll()的放行规则 - 为新增自定义
/login访问路径,参考社区公开方案修改了keycloakAuthenticationProcessingFilter中的RequestMatcher,原以为该配置逻辑合法,但注释掉该自定义Filter的Bean定义后异常立即消失,确认该配置类为问题诱因
问题配置代码
package com.mycompany.myapplication.configurations; import org.keycloak.OAuth2Constants; import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationEntryPoint; import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter; import org.keycloak.adapters.springsecurity.filter.AdapterStateCookieRequestMatcher; import org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter; import org.keycloak.adapters.springsecurity.filter.QueryParamPresenceRequestMatcher; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.OrRequestMatcher; import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; @Configuration @Order(200) public class GeneticistKeycloakAuthenticationProcessingFilter extends KeycloakWebSecurityConfigurerAdapter { @Bean @Override protected KeycloakAuthenticationProcessingFilter keycloakAuthenticationProcessingFilter() throws Exception { final RequestMatcher customRequestMatcher = new OrRequestMatcher( new AntPathRequestMatcher(KeycloakAuthenticationEntryPoint.DEFAULT_LOGIN_URI), new AntPathRequestMatcher("/login/**"), new RequestHeaderRequestMatcher(KeycloakAuthenticationProcessingFilter.AUTHORIZATION_HEADER), new QueryParamPresenceRequestMatcher(OAuth2Constants.ACCESS_TOKEN), new AdapterStateCookieRequestMatcher() ); return new KeycloakAuthenticationProcessingFilter(authenticationManagerBean(),customRequestMatcher); } @Override protected SessionAuthenticationStrategy sessionAuthenticationStrategy() { return null; } }
异常堆栈
Caused by: java.lang.IllegalStateException: permitAll only works with HttpSecurity.authorizeRequests() at org.springframework.util.Assert.state(Assert.java:76) at org.springframework.security.config.annotation.web.configurers.PermitAllSupport.permitAll(PermitAllSupport.java:51) at org.springframework.security.config.annotation.web.configurers.PermitAllSupport.permitAll(PermitAllSupport.java:41) at org.springframework.security.config.annotation.web.configurers.LogoutConfigurer.init(LogoutConfigurer.java:277) at org.springframework.security.config.annotation.web.configurers.LogoutConfigurer.init(LogoutConfigurer.java:69) at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.init(AbstractConfiguredSecurityBuilder.java:338) at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.doBuild(AbstractConfiguredSecurityBuilder.java:300) at org.springframework.security.config.annotation.AbstractSecurityBuilder.build(AbstractSecurityBuilder.java:38) at org.springframework.security.config.annotation.web.builders.WebSecurity.performBuild(WebSecurity.java:302) at org.springframework.security.config.annotation.web.builders.WebSecurity.performBuild(WebSecurity.java:90) at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.doBuild(AbstractConfiguredSecurityBuilder.java:305) at org.springframework.security.config.annotation.AbstractSecurityBuilder.build(AbstractSecurityBuilder.java:38) at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration.springSecurityFilterChain(WebSecurityConfiguration.java:127) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ... 22 common frames omitted
核心疑问
是否存在更简便的实现方式,可让Spring将指定URL识别为登录入口并自动走原生登录流程?
问题根因与简便实现方案
- 异常直接诱因:自定义配置类继承
KeycloakWebSecurityConfigurerAdapter后未重写configure(HttpSecurity http)方法完成基础authorizeRequests()规则配置,同时sessionAuthenticationStrategy()方法直接返回null,导致Spring Security初始化登出配置时找不到授权规则配置节点,抛出状态异常。返回null的会话策略也是登出功能失效的核心原因之一。 - 无需自定义Keycloak认证过滤器即可实现
/login路由映射,步骤如下:- 补全HttpSecurity基础配置,不要返回空的会话策略:
@Override protected void configure(HttpSecurity http) throws Exception { super.configure(http); http .authorizeRequests() .antMatchers("/login", "/static/**").permitAll() .anyRequest().authenticated() .and() .logout() .logoutSuccessUrl("/login") .permitAll(); } // 使用适配器默认提供的会话认证策略即可,禁止返回null @Override protected SessionAuthenticationStrategy sessionAuthenticationStrategy() { return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl()); }- 新增MVC视图控制器配置,将
/login路径直接转发到Keycloak默认授权跳转端点,访问时会自动触发原生OIDC登录流程:
该方案不会改动底层安全过滤链逻辑,不会出现permitAll规则不生效的问题,登出逻辑只要配置对应logout端点即可正常生效。@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { // 旧版Keycloak Spring适配器用DEFAULT_LOGIN_URI,新版Spring Security OAuth2客户端用/oauth2/authorization/keycloak registry.addViewController("/login").setViewName("forward:" + KeycloakAuthenticationEntryPoint.DEFAULT_LOGIN_URI); registry.setOrder(Ordered.HIGHEST_PRECEDENCE); } }
内容的提问来源于stack exchange,提问作者Woodsman
相关产品推荐
相关产品推荐

