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

Spring Boot3升级:SAML扩展迁移至SP遇/saml/login 404问题

Spring Boot 3 + Spring Security 6 SAML2 迁移问题解决方案

问题1:/saml/login 404 与原SAMLEntryPoint替代实现

Spring Security 6对SAML2模块做了重构,原SAMLEntryPoint类已被移除,需通过新的配置方式实现登录跳转逻辑:

1. 配置自定义登录入口路径

在SecurityFilterChain中指定/saml/login作为SAML登录入口,映射到官方SAML2认证端点:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
        .saml2Login(saml2 -> saml2
            .loginPage("/saml/login") // 自定义入口路径
            .authenticationSuccessHandler(new SavedRequestAwareAuthenticationSuccessHandler()) // 自动跳转回原请求页
        )
        .exceptionHandling(ex -> ex
            .authenticationEntryPoint((request, response, ex) -> 
                response.sendRedirect("/saml/login"))); // 未认证请求跳转至SAML登录
    return http.build();
}

2. 实现原TargetUrlSamlEntryPoint的目标URL传递功能

如果需要在跳转时携带目标URL,可通过relayState参数传递,结合自定义Saml2AuthenticationRequestResolver实现:

@Bean
public Saml2AuthenticationRequestResolver customSaml2AuthRequestResolver(
        Saml2RegistrationRepository registrationRepo) {
    OpenSaml4AuthenticationRequestResolver resolver = 
        new OpenSaml4AuthenticationRequestResolver(registrationRepo);
    
    resolver.setAuthenticationRequestContextConsumer(context -> {
        HttpServletRequest request = context.getRequest();
        // 从请求参数或session获取目标URL
        String targetUrl = request.getParameter("target") != null 
            ? request.getParameter("target") 
            : request.getRequestURI();
        
        // 将目标URL存入relayState,认证成功后取出跳转
        context.getAuthenticationRequest().setRelayState(targetUrl);
    });
    return resolver;
}

然后在SecurityFilterChain中注入该Resolver:

.saml2Login(saml2 -> saml2
    .loginPage("/saml/login")
    .authenticationRequestResolver(customSaml2AuthRequestResolver(registrationRepo))
    .authenticationSuccessHandler((request, response, auth) -> {
        String targetUrl = request.getParameter("RelayState");
        if (targetUrl != null && !targetUrl.isEmpty()) {
            response.sendRedirect(targetUrl);
        } else {
            response.sendRedirect("/");
        }
    })
)

问题2:自签名证书的安全处理方式

禁止直接禁用SSL验证,这会引入严重安全风险,推荐以下两种合规方案:

1. 将自签名证书加入JVM信任库

导出Shibboleth的自签名证书:

keytool -exportcert -alias shibboleth-idp -keystore shibboleth.jks -file shibboleth.crt

将证书导入JVM默认信任库(默认密码changeit):

keytool -importcert -alias shibboleth-idp -file shibboleth.crt -keystore $JAVA_HOME/jre/lib/security/cacerts

2. 项目自定义信任库

创建项目专属的信任库,导入证书后在application.properties中配置:

# 自定义信任库配置
server.ssl.trust-store=classpath:truststore.jks
server.ssl.trust-store-password=your-truststore-password
server.ssl.trust-store-type=JKS

也可在SAML2配置中自定义HTTP客户端的SSL上下文:

@Bean
public OpenSaml4Configurer openSaml4Configurer() throws Exception {
    SSLContext sslContext = SSLContextBuilder.create()
        .loadTrustMaterial(ResourceUtils.getFile("classpath:shibboleth.crt"), 
            "cert-password".toCharArray(),
            (certChain, authType) -> {
                // 仅信任导入的自签名证书
                return Arrays.stream(certChain)
                    .anyMatch(cert -> cert.getSubjectDN().getName().contains("Shibboleth IDP"));
            })
        .build();
    
    return OpenSaml4Configurer.custom()
        .httpClient(client -> client.setSSLContext(sslContext))
        .build();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 07:40:32