Xpath转换在java中不起作用

时间:2012-05-22 08:19:42

标签: java xml xslt xpath xml-signature

这是我的xml文档。我想使用xml签名仅签署userID部分。我正在使用xpath转换来选择该特定元素。

<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
Version="2.0" IssueInstant="2012-05-22T13:40:52:390" ProtocolBinding="urn:oasis:na
mes:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL="localhos
t:8080/consumer.jsp">
<UserID>
   xyz
</UserID>
<testing>
   text
</testing>
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
   http://localhost:8080/saml/SProvider.jsp
</saml:Issuer>
</samlp:AuthnRequest>


我使用以下代码添加转换:

transformList.add(exc14nTransform);
 transformList.add(fac.newTransform(Transform.XPATH, new XPathFilterParameterSpec("samlp:AuthnRequest/UserID xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"")));


但我得到以下内容:

Original Exception was javax.xml.transform.TransformerException: Extra illegal t
okens: 'xmlns', ':', 'samlp', '=', '"urn:oasis:names:tc:SAML:2.0:protocol"'


所以,我尝试删除xmlns部分。

transformList.add(fac.newTransform(Transform.XPATH, new XPathFilterParameterSpec("samlp:AuthnRequest/UserID")));


但它签署了整个文件并给出了以下信息:

com.sun.org.apache.xml.internal.security.utils.CachedXPa
thFuncHereAPI fixupFunctionTable
INFO: Registering Here function


有什么问题?
修改
正如@JörnHorstmann所说,这个消息只是一个日志或类似的东西。现在的问题是,即使在给出xpath查询之后,整个文档也会被签名而不仅仅是UserID。我通过在签署文档后更改<testing>元素的值来确认这一点。结果是文档没有得到验证(如果它只签署了UserID部分,那么对<testing>所做的任何更改都应该产生有效的签名。)

1 个答案:

答案 0 :(得分:3)

这不是有效的xpath表达式,没有办法在表达式中声明名称空间prefixe。

samlp:AuthnRequest/UserID xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"

XPathFilterParameterSpec有另一个允许指定名称空间前缀映射的构造函数,您可以尝试以下表达式:

new XPathFilterParameterSpec("samlp:AuthnRequest/UserID",
    Collections.singletonMap("samlp", "urn:oasis:names:tc:SAML:2.0:protocol"))

修改

该消息似乎不是错误,请参阅line 426 here,但其日志级别可能应低于INFO。

我还看了description of xpath filtering

  

对于输入节点集中的每个节点,将对XPath参数中出现的XPath表达式求值一次。结果转换为布尔值。如果布尔值为true,则该节点包含在输出节点集中。如果布尔值为false,则从输出节点集中省略该节点。

因此,仅在签名中包含UserID的正确xpath表达式为self::UserID。但是不要问我这是否真的对xml签名有意义。规范中的示例似乎使用xpath表达式来包含除签名元素本身之外的所有内容:

not(ancestor-or-self::dsig:Signature)

编辑2:

正确的表达式实际上是ancestor-or-self::UserID,因为过滤器还必须包含UserID节点的文本子节点。