微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

创建 QName 异常时,Opensaml unmarshallMessage 给出 opensaml 本地部分不能为“null”

如何解决创建 QName 异常时,Opensaml unmarshallMessage 给出 opensaml 本地部分不能为“null”

我正在使用 Spring SAML,从 IDP 响应我接收颁发者作为属性 ID,所以我想在 spring saml 接收后更改响应,所以我重写了 unmarshall 方法,该方法将解析消息并为此目的更改 xml 元素。在执行此操作时,如果我在解析后直接使用 Element 来解组它正在工作,但是如果我进行 dom 操作,则会给出以下异常。我不明白为什么它在第一个代码中抛出异常,但在下面附加的第二个代码中没有。如何在不再次转换为字符串并获取 dom 对象的情况下使其工作。

Exception in thread "main" java.lang.IllegalArgumentException: local part cannot be "null" when creating a QName
    at java.xml/javax.xml.namespace.QName.<init>(QName.java:185)
    at java.xml/javax.xml.namespace.QName.<init>(QName.java:129)
    at org.opensaml.xml.util.XMLHelper.constructQName(XMLHelper.java:433)
    at org.opensaml.xml.util.XMLHelper.getNodeQName(XMLHelper.java:171)
    at org.opensaml.xml.io.UnmarshallerFactory.getUnmarshaller(UnmarshallerFactory.java:81)
    at org.opensaml.xml.io.AbstractXMLObjectUnmarshaller.unmarshallChildElement(AbstractXMLObjectUnmarshaller.java:334)
    at org.opensaml.xml.io.AbstractXMLObjectUnmarshaller.unmarshall(AbstractXMLObjectUnmarshaller.java:127)
    at org.opensaml.xml.io.AbstractXMLObjectUnmarshaller.unmarshallChildElement(AbstractXMLObjectUnmarshaller.java:355)
    at org.opensaml.xml.io.AbstractXMLObjectUnmarshaller.unmarshall(AbstractXMLObjectUnmarshaller.java:127)
    at org.opensaml.ws.message.decoder.BaseMessageDecoder.unmarshallMessage(unmarshallMessage.java:208)
  1. 对于下面的代码,它抛出异常,如上所述。

    protected XMLObject unmarshallMessage(InputStream messageStream) throws MessageDecodingException {
         log.debug("Parsing message stream into DOM document");
    
         try {
             Document messageDoc = parserPool.parse(messageStream);
             Element messageElem = messageDoc.getDocumentElement();
             Element elementsByTagName = (Element) messageElem.getElementsByTagName("saml2:Assertion").item(0);
             Element issuer = messageDoc.createElement("saml2:Issuer");
             issuer.setTextContent("emIdam");
             issuer.setAttribute("Format","urn:oasis:names:tc:SAML:2.0:nameid-format:entity");
             log.debug("Unmarshalling message DOM");
             Unmarshaller unmarshaller = Configuration.getUnmarshallerFactory().getUnmarshaller(messageElem);
             if (unmarshaller == null) {
                 log.debug("Unable to unmarshall message,no unmarshaller registered for message element "
                         + XMLHelper.getNodeQName(messageElem));
                 throw new MessageDecodingException(
                         "Unable to unmarshall message,no unmarshaller registered for message element "
                                 + XMLHelper.getNodeQName(messageElem));
             }
             XMLObject message = unmarshaller.unmarshall(messageElem);
    
             return message;
         } catch (XMLParserException e) {
             log.error("Encountered error parsing message into its DOM representation",e);
             throw new MessageDecodingException("Encountered error parsing message into its DOM representation",e);
         } catch (UnmarshallingException e) {
             log.error("Encountered error unmarshalling message from its DOM representation",e);
             throw new MessageDecodingException("Encountered error unmarshalling message from its DOM representation",e);
         }
         catch (Exception e) {
             log.warn("Encountered error unmarshalling message from its DOM representation --->",e);
         }
     }
    
  2. 但是对于下面的代码,它工作正常,因为在这里我再次转换为字符串并创建了输入流,然后获取了用于解组的 dom。

    protected XMLObject unmarshallMessage(InputStream messageStream) throws MessageDecodingException {
         log.debug("Parsing message stream into DOM document");
    
         try {
             Document messageDoc = parserPool.parse(messageStream);
             Element messageElem = messageDoc.getDocumentElement();
             Element elementsByTagName = (Element) messageElem.getElementsByTagName("saml2:Assertion").item(0);
             Element issuer = messageDoc.createElement("saml2:Issuer");
             issuer.setTextContent("emIdam");
             issuer.setAttribute("Format","urn:oasis:names:tc:SAML:2.0:nameid-format:entity");
    
             //converting again to string and getting dom
             String xml = XMLHelper.nodetoString(messageElem);
             messageStream = new ByteArrayInputStream(xml.getBytes());
             messageDoc = parserPool.parse(messageStream);
             messageElem = messageDoc.getDocumentElement();
    
    
             log.debug("Unmarshalling message DOM");
             Unmarshaller unmarshaller = Configuration.getUnmarshallerFactory().getUnmarshaller(messageElem);
             if (unmarshaller == null) {
                 log.debug("Unable to unmarshall message,e);
         }
     }
    

解决方法

你的问题可能与你的解析器配置有关,可能没有配置为命名空间感知。

请在初始化您的 parserPool 时使用类似于以下代码的内容:

DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
DocumentBuilder parserPool = documentBuilderFactory.newDocumentBuilder();

我的猜测是第二个测试成功运行,因为在幕后 XMLHelper nodeToString 正在使用 writeNode,而 https://help.poralix.com/articles/mysql-access-denied-you-need-the-super-privilege-for-this-operation 又使用 LSSerializer 来执行实际的 XML 序列化。由于解析器被声明为非命名空间感知的,因此生成的 XML 输出和相应的解析 Document 将不包含命名空间信息,或者至少,它包含的信息使得解析过程随后由 { {1}} 认为合适。

此外,请注意该问题也可能与您创建新 Unmarshaller 的方式有关,因为您没有提供命名空间信息:当您使用 Element 时,生成的 createElement 将不包含 ElementlocalNameprefix,所有这些都设置为 namespaceURI。请改为尝试以下代码:

null

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。