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

升级spring-security-saml2-service-provider 5.6.9遇404错误求助

Spring Security SAML2 5.6.9 整合项目后SP元数据URL及IDP登录返回404

我正在把现有应用从已停止维护的spring-security-saml2-core 1.0.10.RELEASE升级到spring-security-saml2-service-provider 5.6.9。基于GitHub示例搭建的测试应用能正常使用IDP发起登录,也能通过http://{host-name}/saml2/service-provider-metadata/{registration-id}获取SP元数据,但把相同配置整合到实际项目后出现问题:日志显示relyingParty实例配置正常,但访问上述SP元数据URL及尝试IDP发起登录都返回404错误。

配置代码

// Necessary Imports

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private ResourceLoader resourceLoader = new DefaultResourceLoader();


    @Autowired(required = false)
    private RelyingPartyRegistrationRepository relyingPartyRegistrationRepository;

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        LOG.info("In the configure method");
        if (isSAMLEnabled()) {
            LOG.info("Inside IF");
            http
                    .authorizeRequests()
                    .anyRequest().authenticated()
                    .and()
                    .saml2Login(); 

            Converter<HttpServletRequest, RelyingPartyRegistration> relyingPartyRegistrationResolver = new DefaultRelyingPartyRegistrationResolver(relyingPartyRegistrationRepository);
            Saml2MetadataFilter filter = new Saml2MetadataFilter(relyingPartyRegistrationResolver, new OpenSamlMetadataResolver());
            http.addFilterBefore(filter, Saml2WebSsoAuthenticationFilter.class);
        }


        LOG.info("Configure method done.");
    }

    @Bean
    public RelyingPartyRegistrationRepository relyingPartyRegistrationRepository() {

        LOG.info("Inside the bean method");
        if (isSAMLEnabled()) {
            return createRelyingPartyRegistrationRepository();
        } else {
            return null;
        }
    }

    private RelyingPartyRegistrationRepository createRelyingPartyRegistrationRepository() {

        LOG.info("Inside Repo method");


        String entityId = //Appropriate Value
        String ssoUrl = //Appropriate Value
        String certificatePath = //Appropriate Value

        try {
            Resource resource = resourceLoader.getResource(certificatePath);
            InputStream inputStream = resource.getInputStream();
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            X509Certificate certificate = (X509Certificate) cf.generateCertificate(inputStream);
            Saml2X509Credential credential = Saml2X509Credential.verification(certificate);

            RelyingPartyRegistration relyingPartyRegistration = RelyingPartyRegistration
                    .withRegistrationId("okta-idp")
                    .assertingPartyDetails(party -> party
                            .entityId(entityId)
                            .singleSignOnServiceLocation(ssoUrl)
                            .wantAuthnRequestsSigned(false)
                            .verificationX509Credentials(c -> c.add(credential))
                    ).build();

            LOG.info("repo method successful");
            return new InMemoryRelyingPartyRegistrationRepository(relyingPartyRegistration);

        } catch (Exception e) {
            LOG.info("Failed in repo method");
            throw new RuntimeException("Error configuring SAML ", e);
        }
    }

    private boolean isSAMLEnabled() {
        LOG.info("Checking if SAML is enabled...");
        // Logic to check if SAML is enabled, this part works fine.
    }
}

日志信息

2024-01-29 11:36:08,200 INFO Inside the bean method
2024-01-29 11:36:08,200 INFO Checking if SAML is enabled...
2024-01-29 11:36:08,200 INFO Inside Repo method
2024-01-29 11:36:08,212 INFO repo method successful
2024-01-29 11:36:08,324 INFO In the configure method
2024-01-29 11:36:08,324 INFO Checking if SAML is enabled...
2024-01-29 11:36:08,324 INFO Inside IF
2024-01-29 11:36:08,980 INFO Configure method done.

错误信息

HTTP ERROR 404 Not Found
URI: /saml2/service-provider-metadata/{registartion-id}
STATUS:  404
MESSAGE: Not Found
SERVLET: default

排查方向与解决方案

1. 修正请求路径拼写错误

错误日志中的URI包含拼写错误:registartion-id,正确应为registration-id,先确认实际请求的URL是否使用了正确的拼写。

2. 放开元数据端点的匿名访问权限

当前配置中.anyRequest().authenticated()会拦截所有请求,包括SP元数据URL,需要添加例外规则允许匿名访问:

http.authorizeRequests()
    .antMatchers("/saml2/service-provider-metadata/**").permitAll()
    .anyRequest().authenticated()
    .and()
    .saml2Login();

3. 解决Bean注入冲突

代码中同时存在@Autowired注入和自定义RelyingPartyRegistrationRepository Bean的逻辑,可能导致注入异常。直接在configure方法中调用Bean方法获取实例:

// 移除@Autowired的relyingPartyRegistrationRepository字段
@Override
protected void configure(HttpSecurity http) throws Exception {
    LOG.info("In the configure method");
    if (isSAMLEnabled()) {
        LOG.info("Inside IF");
        http
                .authorizeRequests()
                .antMatchers("/saml2/service-provider-metadata/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .saml2Login(); 

        // 直接调用Bean方法获取实例
        Converter<HttpServletRequest, RelyingPartyRegistration> relyingPartyRegistrationResolver = 
            new DefaultRelyingPartyRegistrationResolver(relyingPartyRegistrationRepository());
        Saml2MetadataFilter filter = new Saml2MetadataFilter(relyingPartyRegistrationResolver, new OpenSamlMetadataResolver());
        http.addFilterBefore(filter, Saml2WebSsoAuthenticationFilter.class);
    }
    LOG.info("Configure method done.");
}

4. 检查多Security配置的优先级

如果项目中存在多个WebSecurityConfigurerAdapter配置类,可能会覆盖当前SAML2配置。给当前配置添加@Order(1)注解,确保它的优先级高于其他配置:

@Configuration
@EnableWebSecurity
@Order(1)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    // ... 原有代码
}

5. 验证OpenSAML依赖完整性

Spring Security SAML2 5.x依赖OpenSAML库,确保项目依赖中包含完整的OpenSAML相关包(以Maven为例):

<dependency>
    <groupId>org.opensaml</groupId>
    <artifactId>opensaml-core</artifactId>
    <version>3.4.6</version>
</dependency>
<dependency>
    <groupId>org.opensaml</groupId>
    <artifactId>opensaml-saml-api</artifactId>
    <version>3.4.6</version>
</dependency>
<dependency>
    <groupId>org.opensaml</groupId>
    <artifactId>opensaml-saml-impl</artifactId>
    <version>3.4.6</version>
</dependency>

6. 调试过滤器链加载情况

启用Spring Security的DEBUG日志,查看SAML2相关过滤器是否被正确加载:

logging.level.org.springframework.security=DEBUG

检查日志中是否存在Saml2MetadataFilter和Saml2WebSsoAuthenticationFilter的初始化记录,确认过滤器链是否包含这些组件。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 09:24:59