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

Spring SAML 2.0动态依赖方注册在Nginx反向代理下失效

问题:Spring SAML2动态IdP部署EKS集群后登录重定向失败

业务场景:通过orgId查询参数从其他服务获取对应IdP配置,实现动态选择IdP。本地以Okta作为IdP时功能正常,甚至支持SLO;但部署到EKS集群后,访问http://dev.org.com/services/sso/auth-sso?orgId=<id>可正常跳转至Okta完成登录,登录后重定向阶段无法触发根路径/的认证入口,最终跳转到http://dev.org.com/auth-sso?error。

已尝试的操作:

  • 在application.yml中设置context-path,无效果
  • 查阅负载均衡相关文档,发现当前使用的Spring SAML版本不识别SAMLContextProviderLB或SAMLContextProviderImpl类

依赖配置(build.gradle.kt)

constraints {
    implementation("org.opensaml:opensaml-core:4.1.1")
    implementation("org.opensaml:opensaml-saml-api:4.1.1")
    implementation("org.opensaml:opensaml-saml-impl:4.1.1")
}

// spring
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-security")

// saml2
implementation("org.springframework.security.extensions:spring-security-saml2-core:2.0.0.M31")
implementation("org.springframework.security:spring-security-saml2-service-provider:5.7.4")

安全配置Bean(SamlConfig类)

SecurityFilterChain

@Bean
fun securityWebFilterChain(http: HttpSecurity): SecurityFilterChain {
    
    http
        .authorizeRequests {
            it
            .mvcMatchers("/auth-sso").permitAll()
            .mvcMatchers("/actuator/*").permitAll()
            .anyRequest().authenticated()
        }
        .saml2Login {
            it.loginPage("/auth-sso")
        }
        .saml2Logout{}

    return http.build()
}

自定义RelyingPartyRegistrationRepository

@Bean
protected fun relyingPartyRegistrations(): RelyingPartyRegistrationRepository? {
    return LazyRelyingPartyRegistrationRepository()
}

接口代码

/auth-sso 接口

@GetMapping(value = ["/auth-sso"])
@ResponseBody
fun login(
    @RequestParam(name = "orgId", required = true) orgId: String,
    request: HttpServletRequest,
    response: HttpServletResponse
)  {

    try {

        val id = runBlocking {
            findIdpConfigurationUseCase.execute(object : UserOrganizationLogin {
                override val organizationId = organizationId
                override val token: String? = null
            })
        }

        val spInitiateUrl = "saml2/authenticate/$id"
        log.debug("Redirecting to {}", spInitiateUrl)

        response.sendRedirect(spInitiateUrl)

    }
    catch (e: Exception) {
        log.error("Error preparing assertion info: {}", e)
        response.sendRedirect(MessageFormat.format(environment.getRequiredProperty(HOME_URL), ""))
    }
}

认证入口 / 接口

@RequestMapping("/")
fun index(model: Model, @AuthenticationPrincipal principal: Saml2AuthenticatedPrincipal, response: HttpServletResponse) {

    log.debug("User is authenticated!!!")

    val loginInfo = runBlocking {
        loginUserUseCase.execute(principal)
    }

    response.sendRedirect(
        environment.getRequiredProperty(HOME_URL) +
        MessageFormat.format(environment.getRequiredProperty(SSO_HOME_PARAMS), loginInfo.token, loginInfo.organizationId)
    )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 08:40:26