如何在新版Spring Security中添加SAML RelayState
Spring Security SAML2(5.6.0-RC1)SP发起SSO添加RelayState实现
在旧版OpenSAML及openSAML-extensions库中,为SP发起的SSO添加RelayState很简单——重写SAMLEntryPoint类的WebSSOProfileOptions,再在MessageContext上设置RelayState即可。但升级到对应Spring Security 5.6.0-RC1文档的新版库后,很多开发者找不到实现路径,试过多种方案都没解决。目前不少人用samesite=none Cookie匹配请求响应,但RelayState的实现更优雅、容错性更强,以下是具体实现步骤:
实现步骤
1. 自定义Saml2AuthenticationRequestResolver
创建自定义解析器,在生成认证请求时注入RelayState值:
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationRequestContext; import org.springframework.security.saml2.provider.service.web.authentication.Saml2AuthenticationRequestResolver; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Optional; public class CustomSaml2AuthenticationRequestResolver implements Saml2AuthenticationRequestResolver { private final Saml2AuthenticationRequestResolver delegate; public CustomSaml2AuthenticationRequestResolver(Saml2AuthenticationRequestResolver delegate) { this.delegate = delegate; } @Override public Optional<Saml2AuthenticationRequestContext> resolve(HttpServletRequest request, HttpServletResponse response) { Optional<Saml2AuthenticationRequestContext> context = this.delegate.resolve(request, response); return context.map(ctx -> { // 从请求参数、会话或其他地方获取RelayState,这里示例从请求参数取 String relayState = request.getParameter("relayState"); return Saml2AuthenticationRequestContext.with(ctx) .relayState(relayState) .build(); }); } }
2. 配置SecurityFilterChain替换默认解析器
在Spring Security配置类中,将自定义解析器注入,替换默认实现:
import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver; import org.springframework.security.web.SecurityFilterChain; @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth .anyRequest().authenticated() ) .saml2Login(saml2 -> saml2 .authenticationRequestResolver(resolver -> { OpenSaml4AuthenticationRequestResolver defaultResolver = new OpenSaml4AuthenticationRequestResolver(resolver.getRelyingPartyRegistrationRepository()); resolver.setAuthenticationRequestResolver( new CustomSaml2AuthenticationRequestResolver(defaultResolver) ); }) ); return http.build(); } }
3. 登录成功后获取并使用RelayState
IdP重定向回SP时,Spring Security会自动携带RelayState,你可以通过Saml2AuthenticationToken直接获取:
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationToken; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class AuthController { @GetMapping("/login/saml2/success") public String loginSuccess(Saml2AuthenticationToken token) { String relayState = token.getRelayState(); // 根据业务需求处理RelayState,比如跳转指定页面 return "登录成功,RelayState: " + relayState; } }
内容的提问来源于stack exchange,提问作者Taliebram
相关产品推荐
相关产品推荐

