2013-06-26 20 views
20

Mam aplikację Java do podpisywania dokumentów XML. Po aktualizacji Java do najnowszej wersji (Java7u25) przestaje działać. Pojawia się następujący błąd:Błąd XML dig sig po aktualizacji do java7u25

javax.xml.crypto.dsig.XMLSignatureException: 
javax.xml.crypto.URIReferenceException: 
com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: 
Cannot resolve element with ID ... 

Powrót do java7u21 rozwiązuje problem. Czy jest jakaś zmiana w API XML Dig Sig, która powoduje ten błąd?

+0

Hi Kresok i zapraszamy do stackoverflow. Wziąłem głos, ale proszę zgłosić kompletny stacktrace i spróbować sformatować stacktrace jako kod (za pomocą przycisku '{}'). –

+0

W końcu znalazłem obejście tego nowego ograniczenia Java ... zobacz poniżej – Cerber

Odpowiedz

34

Ten sam problem tutaj. Wydaje się być błędem wewnątrz JVM z powodu ewolucji.

Mam traked go do com.sun.org.apache.xml.internal.security.utils.resolver.implementations.ResolverFragment

w Javie 7u21 & przed:

91: // Element selectedElem = doc.getElementById(id); 
92: selectedElem = IdResolver.getElementById(doc, id); 

w Javie 7u25:

87: selectedElem = doc.getElementById(id); 
    //... 
93: if (secureValidation) { 

secureValidation odnosi się do ewolucji 7u25 java na walidacji XML Sig (patrz changelog), więc muszą mieć uszkodzone zmienił coś innego podczas pracy nad tą ewolucją.

Rozwiązaliśmy ten problem, dostarczając niestandardową javax.xml.crypto.URIDereferencer do javax.xml.crypto.dom.DOMCryptoContext.setURIDereferencer(URIDereferencer), która jest w stanie rozwiązać węzeł, który nie znajduje się jeszcze w drzewie dokumentu DOM (fragmenty w obiekcie XMLObject).

Zgłaszam to teraz do Oracle, zaktualizuję odpowiedź identyfikatorem błędu.


EDIT: Znalazłem to w apache SVN


Edit 2: Dzięki this bug report mam rozumieć, że jest to ewolucja w XML "id" atrybuty obsługi.

Poprzednie wersje Java/JSR-105/SANTUARIO kiedyś bardzo tolerancyjny atrybutów „id” stosowanych w document.getElementById(...) ale ta nowa wersja wymaga atrybut, który jest identyfikowany jako ID XML mówienia. Chodzi mi o to, że nazwanie atrybutu "Id" lub "ID" już nie jest wystarczające, musisz go ostatecznie oznaczyć jako ID, przez weryfikację schematu XSD/DTD.

Niefortunnie, podążam za schematem, który nie jest prawidłowy i dlatego nie można go parsowac przez Javę.

Jeśli znajdujesz się w takiej samej sytuacji, zapoznaj się z poniższym rozwiązaniem. W przeciwnym razie, jeśli dokument XML ma poprawny schemat, spojrzeć na rozwiązania @sherb https://stackoverflow.com/a/17437919/233906

Rozwiązanie

szczęście, można tag atrybutem jako ID, stosując metody jak Element.setIdAttributeNode(org.w3c.dom.Attr,boolean).

Łącząc z małą XPath jak descendant-or-self::*/@Id, aby pobrać Attr węzłów "Id" oraz trochę Java ((Element)attr.getOwnerElement()).setIdAttributeNode(attr,true) powinien wydostać się z kłopotów.

Ale bądź ostrożny:setIdAttributeXXX() jest ważny tylko dla bieżącego dokumentu & węzła. Jeśli clone/adopt/import trzeba zrobić setIdAttributeXXX() o nowych węzłów każdym drzewie DOM

+0

Thx bardzo wszystkim. Wypróbuję twoje rozwiązanie. – kresok

+0

Dzięki Element.setIdAttribute (...) pracował dla mnie, ponieważ nie mam do czynienia z walidacji schematu. – Nikordaris

+2

Wielka praca dochodzeniowa! –

3

I wobec tego samego problemu, a także śledzić ją w dół do fragmentów kodu wymienionych przez Cerber. Jestem ciekawy, czy to błąd, czy zmiana wprowadzona celowo.

Dzięki informacjom podanym w tym wątku Java XML DOM: how are id Attributes special? udało mi się przywrócić do działania.

W skrócie, atrybut "ID" musi być typu "xs: ID" (a nie np. "Xs: string"), aby narzędzie Dereferencer go znalazło. Należy również pamiętać, że w zależności od korzystania z DocumentBuilderFactory należy ustawić schemat XML.

+0

Dzięki SeppSeppler: brakowało mi tej odpowiedzi, która mogłaby mi pomóc – Cerber

+0

Dzięki SeepSeppeler, po utworzeniu XSD (i załadowaniu go do DocumentBuilderFactory) mojego XML, nie miałem tego Problem już, Podpisywanie XML lub Sprawdzanie podpisywania tego samego XML. –

9

Też znalazłem odpowiedzi na to pytanie bardzo pomocne, ale moje rozwiązanie było trochę inne. Pracuję z OpenSAML 2.6.0, a przypisanie schematu do DocumentBuilderFactory tuż przed analizą dokumentu przychodzącego rozwiązało wyjątek ResourceResolverException: Cannot resolve element with ID..., odpowiednio oznaczając atrybuty ID. Oto przykład:

InputStream in = new ByteArrayInputStream(assertion.getBytes());  
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
Schema schema = schemaFactory.newSchema(new URL("http://docs.oasis-open.org/security/saml/v2.0/saml-schema-protocol-2.0.xsd")); 
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
factory.setNamespaceAware(true); 
factory.setSchema(schema); 
Document document = factory.newDocumentBuilder().parse(in); 
+0

Doskonałe i eleganckie rozwiązanie – millhouse

+1

Dla SAML, tak jak w przypadku większości aplikacji, jest to zdecydowanie najlepszy sposób: nie zadzieraj z DOM po załadowaniu, a Ty upewniasz się, że dokument jest załadowany zgodnie ze Schematem. –

+0

Próbowałem tego, ale parsowanie odpowiedzi SAML było bardzo powolne (30sek na OpenJDK 6b32 i Oracle JDK 8u25). Najlepsze, co znalazłem, to użycie ** DOMValidateContext.setIdAttributeNS (...) **. – Tugdual

7

miałem ten sam probleme z kodem:

element.setAttributeNS(null, "Id", elementID); 

FIX: określić id

element.setAttributeNS(null, "Id", elementID); 
Attr idAttr = element.getAttributeNode("Id"); 
element.setIdAttributeNode(idAttr, true); 
1

Jeśli masz

dsObjectChild.setAttribute("Id", "My-id-value"); 

Zmień go

dsObjectChild.setAttribute("Id", "My-id-value"); 
dsObjectChild.setIdAttribute("Id", true); 

on pracuje z java 1.7.0_45

Powiązane problemy