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

SAML2.0+Keycloak+SpringBoot集成报client_not_found错误排查

SAML2集成Keycloak登录报错排查

环境信息

  • Keycloak 18.0.0(Docker本地部署)
  • Spring Boot 2.6.3
  • 集成目标:实现基于SAML 2.0的应用单点登录

故障现象

访问应用端点可正常跳转至Keycloak,但Keycloak控制台持续输出如下报错,登录流程中断:

WARN  [org.keycloak.events] (executor-thread-15) type=LOGIN_ERROR, realmId=my-app, clientId=null, userId=null, ipAddress=172.18.0.1, error=client_not_found, reason=Cannot_match_source_hash

现有配置

WebSecurityConfig.java

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.saml2.provider.service.metadata.OpenSamlMetadataResolver;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
import org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationFilter;
import org.springframework.security.saml2.provider.service.web.DefaultRelyingPartyRegistrationResolver;
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
import org.springframework.security.saml2.provider.service.web.Saml2MetadataFilter;

import static org.springframework.security.config.Customizer.withDefaults;

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private final RelyingPartyRegistrationRepository relyingPartyRegistrationRepository;

    public WebSecurityConfig(RelyingPartyRegistrationRepository relyingPartyRegistrationRepository) {
        this.relyingPartyRegistrationRepository = relyingPartyRegistrationRepository;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        RelyingPartyRegistrationResolver defaultRelyingPartyRegistrationResolver = new DefaultRelyingPartyRegistrationResolver(relyingPartyRegistrationRepository);
        Saml2MetadataFilter filter = new Saml2MetadataFilter(defaultRelyingPartyRegistrationResolver, new OpenSamlMetadataResolver());

        http
                .saml2Login(withDefaults())
                .addFilterBefore(filter, Saml2WebSsoAuthenticationFilter.class)
                .antMatcher("/**")
                .authorizeRequests()
                .antMatchers("/**").authenticated();
    }
}

pom.xml 核心依赖

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-saml2-service-provider</artifactId>
</dependency>

application.yml SAML配置片段

spring:
  security:
    saml2:
      relyingparty:
        registration:
          saml:
            identityprovider:
              entity-id: http://localhost:8080/realms/my-app
              verification:
                  - certificate-location: "classpath:saml-certificate/keycloak.cert"
              singlesignon:
                url: http://localhost:8080/auth/realms/my-app/protocol/saml
                sign-request: false

问题根因与修复方案

报错Cannot_match_source_hash且clientId=null的核心原因是Keycloak收到SAML认证请求后,无法通过请求携带的信息匹配到对应realm下的配置客户端,结合现有配置,具体问题和修复步骤如下:

  1. 修正Keycloak路径配置不一致问题
    Keycloak 18.0.0基于Quarkus重构后,默认移除了旧版本WildFly发行版自带的/auth上下文根路径,只有启动时手动添加--http-relative-path=/auth参数才会保留该前缀。
    你当前配置中IdP的entity-id使用不带/auth的路径,SSO地址却带/auth前缀,二者不匹配会导致请求路由异常。如果启动Keycloak时未指定上述参数,请将singlesignon.url修改为http://localhost:8080/realms/my-app/protocol/saml,和entity-id路径保持一致;如果需要保留/auth前缀,启动Keycloak时添加对应参数,同时将entity-id也修改为带/auth的格式即可。

  2. 补全Spring SAML2 SP侧缺失配置
    你当前的配置仅填写了IdP(Keycloak)侧参数,未配置SP(当前Spring应用)自身的实体ID、ACS地址参数。Spring Security SAML2默认会按规则生成SP参数:

    • 默认SP Entity ID(对应SAML请求中的Issuer字段):{应用访问根地址}/saml2/service-provider-metadata/{registrationId},当前registrationId为saml
    • 默认ACS(断言消费服务)地址:{应用访问根地址}/login/saml2/sso/{registrationId}
      你可以选择直接使用默认值,也可以在application.yml中手动指定固定值避免环境变化导致匹配失败,补全后的配置示例如下:
    spring:
      security:
        saml2:
          relyingparty:
            registration:
              saml:
                # SP侧配置,需和Keycloak侧客户端参数完全一致
                entity-id: my-spring-boot-app # 可自定义,作为Keycloak侧SAML客户端的Client ID
                acs:
                  location: http://localhost:8081/login/saml2/sso/saml # 替换为Spring应用实际访问地址+默认ACS路径
                identityprovider:
                  entity-id: http://localhost:8080/realms/my-app
                  verification:
                      - certificate-location: "classpath:saml-certificate/keycloak.cert"
                  singlesignon:
                    url: http://localhost:8080/realms/my-app/protocol/saml
                    sign-request: false
    
  3. 修正Keycloak侧SAML客户端配置
    进入Keycloak的my-app realm,按如下要求配置SAML客户端:

    • 客户端类型选择SAML
    • Client ID字段必须和Spring配置中entity-id的值完全一致,不能存在拼写、斜杠、前后缀差异
    • 有效重定向URI配置为Spring应用的ACS地址,格式为http://localhost:8081/login/saml2/sso/saml/*(末尾加通配符适配请求参数)
    • 为避免手动填写参数出错,可以启动Spring应用后访问http://localhost:8081/saml2/metadata/saml获取SP元数据文件,创建客户端时直接选择导入元数据,即可自动填充所有匹配参数。

你当前的WebSecurityConfig代码本身没有逻辑问题,不需要额外调整,完成以上配置后重启应用即可正常走通SAML登录流程。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 00:15:43