Apache Camel中XML Security组件实现分离式XML签名的Schema配置问题
问题:Apache Camel分离式XML签名无法生成验证Schema,指定元素签名失效
我在实现**分离式XML签名(Detached XML Signatures)**时碰到了两个棘手的问题:
- 按照官方示例配置后,始终无法生成用于验证的
test.xsdSchema文件 - 尝试对已加密请求里的
Body、Timestamp和BinarySecurityToken三个元素签名,但配置后完全没达到预期效果
以下是我的Camel Blueprint路由配置、待签名元素配置,以及截断的签名URI:
完整路由配置
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:camel="http://camel.apache.org/schema/blueprint" xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0" xmlns:cxf="http://camel.apache.org/schema/blueprint/cxf" xmlns:http="http://cxf.apache.org/transports/http/configuration" xmlns:sec="http://cxf.apache.org/configuration/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd"> <camel:keyStoreParameters id="injks" password="desarrollo" resource="C:/Users/Usuario/Desktop/nuevo/test.jks"/> <bean class="org.apache.camel.util.jsse.KeyStoreParameters" id="keyStore2"> <property name="resource" value="C:/Users/Usuario/Desktop/nuevo/test.jks"/> <property name="password" value="development"/> </bean> <bean class="org.apache.camel.component.xmlsecurity.api.DefaultKeyAccessor" id="keyAccessorOne"> <property name="alias" value="test"/> <property name="password" value="development"/> <property name="keyStoreParameters" ref="keyStore2"/> </bean> <!-- Parts --> <bean class="java.util.ArrayList" id="xpathParts"> <argument> <list> <bean class="org.apache.camel.component.xmlsecurity.api.XmlSignatureHelper" factory-method="getXpathFilter"> <argument type="java.lang.String" value="//*:Body"/> </bean> <bean class="org.apache.camel.component.xmlsecurity.api.XmlSignatureHelper" factory-method="getXpathFilter"> <argument type="java.lang.String" value="//*:Timestamp"/> </bean> <bean class="org.apache.camel.component.xmlsecurity.api.XmlSignatureHelper" factory-method="getXpathFilter"> <argument type="java.lang.String" value="//*:BinarySecurityToken"/> </bean> </list> </argument> </bean> <camelContext id="context-redbanc" xmlns="http://camel.apache.org/schema/blueprint"> <route id="_route1"> <from id="_from1" uri="timer:foo?period=20000"/> <setBody id="_setBody1"> <simple>resource:classpath:etc/wsdl/schema.xml</simple> </setBody> <marshal id="_marshal2"> <jaxb contextPath="cl.coopeuch.integracion.wsredbanc.wsdl.test"/> </marshal> <marshal id="_marshal1"> <secureXML id="inEncryption" keyCipherAlgorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" keyOrTrustStoreParametersId="injks" recipientKeyAlias="des-wls02.rbc.cl" secureTag="//*:Body" secureTagContents="true" xmlCipherAlgorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/> </marshal> <setHeader headerName="CamelXmlSignatureContentReferenceUri" id="_setHeader1"> <constant>#Body</constant> </setHeader> <to id="_to2" uri="xmlsecurity:sign://oneSign?keyAccessor=#keyAccessorOne&amp;digestAlgorithm=http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23sha1&amp;xpathsToIdAttributes=#xpathParts&amp;schemaResourceUri=etc/wsdl/schema.xsd"/> <to id="_to3" uri="file://C:/Users/Usuario/Desktop/salida?fileName=outbound_body.xml"/> <to id="_to4" uri="mock:result"/> </route> </camelContext> </blueprint>
待签名元素配置
<bean class="java.util.ArrayList" id="xpathParts"> <argument> <list> <bean class="org.apache.camel.component.xmlsecurity.api.XmlSignatureHelper" factory-method="getXpathFilter"> <argument type="java.lang.String" value="//*:Body"/> </bean> <bean class="org.apache.camel.component.xmlsecurity.api.XmlSignatureHelper" factory-method="getXpathFilter"> <argument type="java.lang.String" value="//*:Timestamp"/> </bean> <bean class="org.apache.camel.component.xmlsecurity.api.XmlSignatureHelper" factory-method="getXpathFilter"> <argument type="java.lang.String" value="//*:BinarySecurityToken"/> </bean> </list> </argument> </bean>
截断的签名URI
<to id="_to2" uri="xmlsecurity:sign://oneSign?keyAccessor=#keyAccessorOne&amp;digestAlgorithm=http%3A%2F%2Fwww.w3.org%2F200"/>
问题排查与修正方案
1. Schema生成失败的核心原因与解决
- 路径与参数配置问题:你指定的
schemaResourceUri=etc/wsdl/schema.xsd必须确保文件在Camel的类路径下(比如打包后要在META-INF或指定资源目录),同时需要添加generateSchema=true参数明确开启Schema生成(默认是关闭的) - 加密后结构影响:加密后的
Body会被<xenc:EncryptedData>包裹,原XPath可能无法匹配,导致组件无法正确解析结构生成Schema,需要先确认加密后的XML结构是否符合预期
2. 指定元素签名失效的修正
你的配置里犯了一个关键错误:xpathsToIdAttributes参数是用来给指定元素添加ID属性的,不是用来指定待签名元素的。要指定签名部分,应该用xmlSignatureParts参数,配合XmlSignatureHelper.getSignaturePart()方法创建签名项:
修正后的待签名元素配置
<bean class="java.util.ArrayList" id="signatureParts"> <argument> <list> <!-- 签名Body元素(注意加密后可能需要调整XPath) --> <bean class="org.apache.camel.component.xmlsecurity.api.XmlSignatureHelper" factory-method="getSignaturePart"> <argument type="java.lang.String" value="//*:Body"/> <argument type="java.lang.String" value="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> </bean> <!-- 签名Timestamp元素 --> <bean class="org.apache.camel.component.xmlsecurity.api.XmlSignatureHelper" factory-method="getSignaturePart"> <argument type="java.lang.String" value="//*:Timestamp"/> <argument type="java.lang.String" value="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> </bean> <!-- 签名BinarySecurityToken元素 --> <bean class="org.apache.camel.component.xmlsecurity.api.XmlSignatureHelper" factory-method="getSignaturePart"> <argument type="java.lang.String" value="//*:BinarySecurityToken"/> <argument type="java.lang.String" value="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> </bean> </list> </argument> </bean>
修正后的完整签名URI
添加分离式签名类型、Schema生成参数,替换正确的签名部分参数:
<to id="_to2" uri="xmlsecurity:sign://oneSign?keyAccessor=#keyAccessorOne&digestAlgorithm=http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23sha1&xmlSignatureParts=#signatureParts&signatureType=DETACHED&schemaResourceUri=etc/wsdl/schema.xsd&generateSchema=true"/>
加密后Body的XPath调整
如果加密后的Body被<xenc:EncryptedData>包裹,你需要修改XPath并在加密配置中指定ID:
<!-- 加密配置添加secureTagId --> <marshal id="_marshal1"> <secureXML id="inEncryption" keyCipherAlgorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" keyOrTrustStoreParametersId="injks" recipientKeyAlias="des-wls02.rbc.cl" secureTag="//*:Body" secureTagId="Body-Encrypted" secureTagContents="true" xmlCipherAlgorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/> </marshal> <!-- 签名部分的XPath改为匹配加密后的节点 --> <bean class="org.apache.camel.component.xmlsecurity.api.XmlSignatureHelper" factory-method="getSignaturePart"> <argument type="java.lang.String" value="//xenc:EncryptedData[@Id='Body-Encrypted']"/> <argument type="java.lang.String" value="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> </bean>
额外调试建议
开启Camel的DEBUG日志级别,查看org.apache.camel.component.xmlsecurity包下的日志,能清晰看到元素匹配、签名生成、Schema生成的详细过程,快速定位问题点。另外建议先测试未加密的XML签名,确认签名逻辑正常后再加入加密步骤,分步排查更高效。
内容的提问来源于stack exchange,提问作者ctoledo
相关产品推荐
相关产品推荐

