Преобразование Xpath не работает в Java
-
12-12-2019 - |
Вопрос
Это мой XML-документ.Я хочу подписать только часть userID, используя подпись xml.Я использую преобразование 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örn Horstmann, сообщение — это просто журнал или что-то в этом роде.Теперь проблема в том, что даже после запроса xpath подписывается весь документ, а не только UserID.Я подтвердил это, изменив значение <testing>
элемент после подписания документа.В результате документ не проходит проверку (если он подписал только часть UserID, то любые изменения, внесенные в <testing>
должна привести к действительной подписи.)
Решение
Это недопустимое выражение xpath, внутри выражения невозможно объявить префикс пространства имен.
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"))
Редактировать:
Сообщение не является ошибкой, см. строка 426 здесь, его уровень журнала, вероятно, должен быть ниже, чем INFO.
Я также посмотрел на описание фильтрации XPath:
Выражение XPath, появляющееся в параметре XPath, оценивается один раз для каждого узла во входном наборе узлов.Результат преобразуется в логическое значение.Если логическое значение истинно, то узел включается в выходной набор узлов.Если логическое значение ложно, то узел исключается из выходного набора узлов.
Таким образом, правильное выражение xpath, включающее только UserID
в подписи будет self::UserID
.Но не спрашивайте меня, действительно ли это имеет смысл для подписи XML.Кажется, что в примере в спецификации используется выражение xpath, включающее все, кроме самого элемента подписи:
not(ancestor-or-self::dsig:Signature)
Редактировать 2:
Правильное выражение на самом деле ancestor-or-self::UserID
поскольку фильтр также должен включать текстовые дочерние узлы UserID
узел.