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

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识别为登录入口并自动走原生登录流程?

问题根因与简便实现方案

  1. 异常直接诱因:自定义配置类继承KeycloakWebSecurityConfigurerAdapter后未重写configure(HttpSecurity http)方法完成基础authorizeRequests()规则配置,同时sessionAuthenticationStrategy()方法直接返回null,导致Spring Security初始化登出配置时找不到授权规则配置节点,抛出状态异常。返回null的会话策略也是登出功能失效的核心原因之一。
  2. 无需自定义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登录流程:
    @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);
        }
    }
    
    该方案不会改动底层安全过滤链逻辑,不会出现permitAll规则不生效的问题,登出逻辑只要配置对应logout端点即可正常生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 13:57:13