SpringSecurity SAML(OpenSAML):无法取消编组断言:获取org.w3.dom.DOMExcep



使用spring-security-saml处理来自IDP的断言,在服务器运行1到2小时后会出现以下错误。问题并非总是可重现的。通过查看stacktrace,这个问题似乎和springsaml配置中使用的解析器池有关。请分享你的想法。

库版本:opensaml 2.6.1spring-security-saml2 1.0.0.发布

分析器池配置:

<bean id="parserPool" class="org.opensaml.xml.parse.StaticBasicParserPool" init-method="initialize">
    <property name="builderFeatures">
        <map>
            <entry key="http://apache.org/xml/features/dom/defer-node-expansion" value="false"/>
        </map>
    </property>
</bean>
<bean id="parserPoolHolder" class="org.springframework.security.saml.parser.ParserPoolHolder"/>

堆栈跟踪为:

org.w3c.dom.DOMException: WRONG_DOCUMENT_ERR: A node is used in a different document than the one that created it. 
        at org.apache.xerces.dom.ParentNode.internalInsertBefore(Unknown Source) 
        at org.apache.xerces.dom.ParentNode.insertBefore(Unknown Source) 
        at org.apache.xerces.dom.NodeImpl.appendChild(Unknown Source) 
        at org.opensaml.xml.encryption.Decrypter.parseInputStream(Decrypter.java:821) 
        at org.opensaml.xml.encryption.Decrypter.decryptDataToDOM(Decrypter.java:599) 
        at org.opensaml.xml.encryption.Decrypter.decryptUsingResolvedEncryptedKey(Decrypter.java:784) 
        at org.opensaml.xml.encryption.Decrypter.decryptDataToDOM(Decrypter.java:524) 
        at org.opensaml.xml.encryption.Decrypter.decryptDataToList(Decrypter.java:442) 
        at org.opensaml.xml.encryption.Decrypter.decryptData(Decrypter.java:403) 
        at org.opensaml.saml2.encryption.Decrypter.decryptData(Decrypter.java:141) 
        at org.opensaml.saml2.encryption.Decrypter.decrypt(Decrypter.java:69) 
        at org.springframework.security.saml.websso.WebSSOProfileConsumerImpl.processAuthenticationResponse(WebSSOProfileConsumerImpl.java:199) 
        at org.springframework.security.saml.SAMLAuthenticationProvider.authenticate(SAMLAuthenticationProvider.java:82) 

根本原因:项目中xerces的多个实现。

发现问题。我的项目也有用于word文档处理的docx4j,docx4j在初始化时将系统属性javax.xml.parsers.DocumentBuilderFactory更改为"com.sun.org/apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl",如果系统属性尚未设置,并且java版本<8,这在内部导致返回一个DocumentBuilderFactory实现,该实现与opensaml初始化时使用的实现不同。即org.apache.xerces.internal.axp.DocumentBuilderFactoryImpl

Fix正在使用以下java运行时选项将系统属性javax.xml.parsers.DocumentBuilderFactory设置为com.sun.org.apache.xerces.internal.axp.DocumentBuilderFactoryImpl

-Djavax.xml.parsers.DocumentBuilderFactory=com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl

正如@Srini所说,根本原因是项目中xerce的多个实现。

我通过重写docx4j.properties:中的docx4j属性解决了这个问题

javax.xml.parsers.DocumentBuilderFactory=org.apache.xerces.jaxp.DocumentBuilderFactoryImpl

最新更新