如何在Spring Boot SP中配置Spring Security生成含Assertion的SAML请求
基于Spring Boot的SAML请求格式配置问题
我已经基于Spring Boot实现了一个Service Provider(SP),需要生成特定格式的SAML请求,目标格式如下:
<saml:Assertion Version="2.0" ID="_e2294424-9055-4b32-ac27-39c1c53f66e7" IssueInstant="2023-08-03T09:09:30.036Z" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"> <samlp:AuthnRequest Version="2.0" IssueInstant="2023-08-03T09:09:30.036Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL=..... xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" /> <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity" >..... </saml2:Issuer> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">..</ds:Signature> </saml:Assertion>
当前我生成的请求格式不符合要求,无法插入<saml:Assertion>标签,当前生成的内容如下:
<samlp:AuthnRequest Version="2.0" IssueInstant="2023-08-03T09:09:30.036Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL=..... xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" /> <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity" >...... </saml2:Issuer> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">..</ds:Signature> </samlp:AuthnRequest>
解决方案
首先需要明确:SAML 2.0规范中,AuthnRequest(认证请求)本身就是根元素,Assertion是身份提供者(IdP)返回的断言内容,并非SP发送的AuthnRequest的父元素。你想要的格式不符合标准SAML 2.0协议规范,但如果对接的IdP有特殊要求,可通过以下方式自定义XML结构:
1. 自定义SAML消息转换器
继承Spring Security SAML的Saml2MessageConverter,重写转换方法,在生成的AuthnRequest外层包裹<saml:Assertion>标签:
@Component public class CustomSaml2MessageConverter extends Saml2MessageConverter { @Override protected String convert(Saml2Request request) { // 获取默认生成的AuthnRequest XML String originalAuthnRequest = super.convert(request); // 动态生成Assertion的ID和IssueInstant String assertionId = "_" + UUID.randomUUID(); String issueInstant = Instant.now().toString(); // 构造外层Assertion包裹结构 return String.format(""" <saml:Assertion Version="2.0" ID="%s" IssueInstant="%s" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"> %s <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">..</ds:Signature> </saml:Assertion> """, assertionId, issueInstant, originalAuthnRequest); } }
2. 替换默认转换器到Spring Security配置
在安全配置类中注册自定义转换器,替换默认的消息转换逻辑:
@Configuration @EnableWebSecurity public class SecurityConfig { private final CustomSaml2MessageConverter customSaml2MessageConverter; public SecurityConfig(CustomSaml2MessageConverter customSaml2MessageConverter) { this.customSaml2MessageConverter = customSaml2MessageConverter; } @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()) .saml2Login(saml2 -> saml2 .authenticationConverter(customSaml2MessageConverter) ); return http.build(); } }
3. 注意事项
- 务必动态生成
Assertion的ID和IssueInstant,避免硬编码导致重复或无效值 - 如果需要对整个外层
Assertion进行签名,需调整签名逻辑:默认Spring Security仅对AuthnRequest签名,需自定义签名处理器,对包裹后的完整XML进行签名操作 - 这种自定义格式属于非标准用法,仅适用于对接有特殊要求的IdP,建议优先与IdP方确认是否可遵循标准SAML 2.0规范对接
内容的提问来源于stack exchange,提问作者Luca Rossi
相关产品推荐
相关产品推荐

