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

Azure AD SAML2 SSO对接问题:Spring Boot+AWS ELB协议端口异常

解决Spring Security SAML2在AWS ELB下回复URL协议/端口异常问题

针对部署在ECS的Spring Boot应用,通过SSL终止的ELB访问时,SAML认证请求中回复URL自动变为http和8443的问题,提供以下解决思路:

1. 开启Spring Boot的反向代理转发头支持

ELB作为反向代理会传递X-Forwarded-Proto(前端协议)、X-Forwarded-Port(前端端口)等头信息,Spring Boot需要正确识别这些头来生成外部真实URL。在application.yml中添加配置:

server:
  forward-headers-strategy: framework
  tomcat:
    remoteip:
      remote-ip-header: X-Forwarded-For
      protocol-header: X-Forwarded-Proto
      port-header: X-Forwarded-Port

或application.properties格式:

server.forward-headers-strategy=framework
server.tomcat.remoteip.remote-ip-header=X-Forwarded-For
server.tomcat.remoteip.protocol-header=X-Forwarded-Proto
server.tomcat.remoteip.port-header=X-Forwarded-Port

该配置让Spring Boot使用框架原生机制处理转发头,确保内部请求能获取到外部的HTTPS协议和正确端口。

2. 手动指定SAML2的ACS(断言消费者服务)URL

避免框架自动推断URL时出错,直接在RelyingPartyRegistration中强制指定ACS的完整HTTPS地址:

@Bean
public RelyingPartyRegistrationRepository relyingPartyRegistrationRepository() {
    RelyingPartyRegistration azureAdRegistration = RelyingPartyRegistrations
            .fromMetadataLocation("classpath:azure-ad-saml-metadata.xml")
            .registrationId("azure-ad-sso")
            .acsLocation("https://our-domain.com/saml/sso") // 明确指定外部ACS URL
            .build();
    return new InMemoryRelyingPartyRegistrationRepository(azureAdRegistration);
}

配置后,Spring Security生成SAML认证请求时会直接使用指定的URL,不再依赖请求上下文推断。

3. 验证ELB的转发头配置

确保ELB的HTTPS监听器已开启转发必要头信息:

  • 登录AWS控制台进入目标ELB的监听器配置页
  • 检查HTTPS监听器的"转发头"设置,确认X-Forwarded-Proto、X-Forwarded-Port已启用传递

4. 自定义Filter修正请求上下文(兜底方案)

若上述配置未解决问题,可自定义Filter手动覆盖请求的scheme和端口:

@Component
public class ForwardedUrlCorrectionFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String protoHeader = request.getHeader("X-Forwarded-Proto");
        String portHeader = request.getHeader("X-Forwarded-Port");
        
        if (protoHeader != null && portHeader != null) {
            HttpServletRequest wrappedRequest = new HttpServletRequestWrapper(request) {
                @Override
                public String getScheme() {
                    return protoHeader;
                }

                @Override
                public int getServerPort() {
                    return Integer.parseInt(portHeader);
                }

                @Override
                public StringBuffer getRequestURL() {
                    StringBuffer originalUrl = super.getRequestURL();
                    String originalScheme = super.getScheme();
                    int originalPort = super.getServerPort();
                    return new StringBuffer(originalUrl.toString()
                            .replace(originalScheme + "://", protoHeader + "://")
                            .replace(":" + originalPort, ":" + portHeader));
                }
            };
            filterChain.doFilter(wrappedRequest, response);
        } else {
            filterChain.doFilter(request, response);
        }
    }
}

然后在Spring Security配置中,将该Filter添加到SAML2相关Filter之前:

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    private final ForwardedUrlCorrectionFilter forwardedUrlFilter;

    public SecurityConfig(ForwardedUrlCorrectionFilter forwardedUrlFilter) {
        this.forwardedUrlFilter = forwardedUrlFilter;
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .addFilterBefore(forwardedUrlFilter, Saml2WebSsoAuthenticationFilter.class)
                .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
                .saml2Login(saml2 -> saml2
                        .relyingPartyRegistrationRepository(relyingPartyRegistrationRepository()));
        return http.build();
    }

    // 此处省略RelyingPartyRegistrationRepository的配置
}

补充说明

旧版Spring Security SAML扩展中的SAMLContextProviderLB已在新版Spring Security SAML2中移除,新版已整合反向代理处理机制,上述方案均基于新版标准实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 05:40:30