XPath Transformation non funziona in Java
-
12-12-2019 - |
Domanda
Questo è il mio documento XML. Voglio firmare solo la parte userid usando la firma XML. Sto usando la trasformazione XPath per selezionare quel particolare elemento.
<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>
.
Sto usando il seguente codice per aggiungere le trasformazioni:
transformList.add(exc14nTransform);
transformList.add(fac.newTransform(Transform.XPATH, new XPathFilterParameterSpec("samlp:AuthnRequest/UserID xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"")));
.
Ma ottengo quanto segue:
Original Exception was javax.xml.transform.TransformerException: Extra illegal t
okens: 'xmlns', ':', 'samlp', '=', '"urn:oasis:names:tc:SAML:2.0:protocol"'
.
Quindi, ho provato a rimuovere la parte XMLNS.
transformList.add(fac.newTransform(Transform.XPATH, new XPathFilterParameterSpec("samlp:AuthnRequest/UserID")));
.
Ma firma l'intero documento e fornisce il seguente messaggio:
com.sun.org.apache.xml.internal.security.utils.CachedXPa
thFuncHereAPI fixupFunctionTable
INFO: Registering Here function
.
Qual è il problema?
Modifica
Come @ Jörn Horstmann ha detto che il messaggio è solo un registro o qualcosa del genere. Ora il problema è che anche dopo aver dato la query XPath, l'intero documento è firmato al posto del solo ID utente. L'ho confermato modificando il valore del <testing>
element dopo aver firmato il documento. Il risultato è che il documento non viene convalidato (se ha firmato solo la parte userid, quindi eventuali modifiche apportate a <testing>
dovrebbero causare una firma valida.)
Soluzione
Questa non è un'espressione XPath valida, non c'è modo di dichiarare il prefisso del namespace all'interno dell'espressione.
samlp:AuthnRequest/UserID xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
.
XPathFilterParameterspec ha un altro costruttore che consente di specificare una mappatura dei prefissi dei nomi, è possibile provare la seguente espressione:
new XPathFilterParameterSpec("samlp:AuthnRequest/UserID",
Collections.singletonMap("samlp", "urn:oasis:names:tc:SAML:2.0:protocol"))
.
Modifica:
Il messaggio non sembra essere un errore, vedere linea 426 qui , il suo livello di registro dovrebbe probabilmente essere più basso delle informazioni però.
Ho anche dato un'occhiata a Descrizione del filtro XPath :
.L'espressione XPath che appare nel parametro XPath viene valutata una volta per ciascun nodo nel set di nodi di ingresso. Il risultato è convertito in un booleano. Se il booleano è vero, il nodo è incluso nel set di nodi di output. Se il booleano è falso, il nodo viene omesso dal nodo di uscita.
Quindi l'espressione di XPath corretta per includere solo il UserID
nella firma sarebbe self::UserID
. Ma non chiedermi se questo ha effettivamente senso per una firma XML. L'esempio nella specifica sembra usare un'espressione XPath per includere tutto tranne l'elemento firma stesso:
not(ancestor-or-self::dsig:Signature)
.
Modifica 2:
L'espressione corretta è in realtà ancestor-or-self::UserID
poiché il filtro deve anche includere i nodi del figlio del testo del nodo UserID
.