我想在我的项目中防止XXE攻击。它是在java7(没有maven)和jbost-as-7服务器上运行的旧api项目。但是在执行过程中,我得到了错误:org. xml.sax.SAXNot识别的异常:属性'超文本传输协议://javax.xml.XML常量/属性/访问外部DTD'无法识别。
org.xml.sax.SAXNotRecognizedException: Property 'http://javax.xml.XMLConstants/property/accessExternalDTD' is not recognized.
15:19:02,845 ERROR [stderr] (http-localhost-127.0.0.1-8080-3) at org.apache.xerces.jaxp.validation.ValidatorImpl.setProperty(ValidatorImpl.java:218)
15:19:02,846 ERROR [stderr] (http-localhost-127.0.0.1-8080-3) at com.uid.kua.web.KUARestController.authenticateAtAUA(KUARestController.java:118)
15:19:02,847 ERROR [stderr] (http-localhost-127.0.0.1-8080-3) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
15:19:02,847 ERROR [stderr] (http-localhost-127.0.0.1-8080-3) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
15:19:02,848 ERROR [stderr] (http-localhost-127.0.0.1-8080-3) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
15:19:02,849 ERROR [stderr] (http-localhost-127.0.0.1-8080-3) at java.lang.reflect.Method.invoke(Method.java:606)
我已经搜索过了,每个论坛都有不同的含义,说这是一个bug。我没有找到任何相关的解决方案。请帮助。事先感谢。
最后我解决了它。我发布了答案,以防这对任何人都有帮助。在经历了在线解决方案后,我无法检测到导致上述错误的主要问题。对于xxe预防,我们需要一些定义的属性,如:XML常量。ACCESS_EXTERNAL_DTDXML常量。ACCESS_EXTERNAL_SCHEMA
我们需要xerces和jaxp-api jar来传递xml,并通过设置上面的一些属性来防止api提供的xxe解析xml。在JDK7之前,这些已经包含在JDK7和更高版本中。所以我们不需要在项目类路径中导入上面的jar。
在我的例子中,我使用jboss-as-7.1.1.Final作为应用服务器,它也有自己的xercesjar(org. apache.xerces.)。但是java也有自己的xerces和jaxp实现(com.sun.xerces.)。所以在部署战争时,我们得到了上面的错误,因为这两个罐子在jboss加载它自己的xerces罐子时相互冲突。
解决方案:我们需要通过在jboss/org/apache/xerces/main/模块. xml文件中进行更改来排除jboss xerces实现。注释如下所示的行:
> <module xmlns="urn:jboss:module:1.1" name="org.apache.xerces">
> <!--
> <resources>
> <resource-root path="xercesImpl-2.9.1-jbossas-1.jar"/>
> Insert resources here
> </resources>
> -->
> <dependencies>
> <module name="javax.api"/>
> </dependencies>
>
> </module>
现在部署并运行您的应用程序。快乐编码。
JAXP 1.5中似乎引入了访问外部DTD和访问外部模式的属性。然而,JavaEE6(甚至仍然JavaEE8)只随JAXP 1.4一起提供。
在我的例子中(运行在WildFly 19和AdoptOpenJDK 11上),我能够通过使用Java9中引入的静态newDefaultInstance()方法来获取JDK的DocumentBuilderFactory和SchemaFactory的默认实例。在Java8中,这两个类都有一个newInstance方法,您可以在其中指定类名,即com.sun.org. apache.xercs.interal.jaxp.DocumentBuilderFactoryImpl和com.sun.org.apache.xercs.interal.jaxp.validation.XMLSchemaFactory。
此解决方案避免更改JBoss模块。
javax. xml通过几个选项加载某些Factory接口的实现。第一个选项是通过系统属性配置默认实现。例如:
javax.xml.validation.SchemaFactory:http://www.w3.org/2001/XMLSchema = com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory
javax.xml.parsers.DocumentBuilderFactory = com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
第二种选择是使用jaxb.properties文件,你必须包含在你的jre或jdk如何做到这一点在这里描述:https://docs.oracle.com/javase/tutorial/jaxp/properties/usingProps.html
第三个选项是在META-INF/services中添加一个文件,该文件的名称应该是要为其定义实现的Factory接口,并且该文件应该包含实现的完整包名类名。例如,您可以添加一个名为javax. xml.parser.DocumentBuilderFactory的文件,其中包含com.sun.org.apache.xerces.内部.jaxp.DocumentBuilderFactoryImpl
第四个选项是选择默认实现。在Wildfly/Jboss的情况下,他们包含了一个只支持JAXP 1.4的org. apache.xerces实现。这意味着它将选择此实现,这就是您收到错误的原因。
要找出哪个实现用于您的特定功能,您可以添加一个系统属性
jaxp.debug = 1
此属性将为jaxp启用调试模式,您将看到以下输出:
JAXP: using thread context class loader (ModuleClassLoader for Module "deployment.css-private-build-1.0-SNAPSHOT.ear.css-private.war" from Service Module Loader) for search
JAXP: Looking up system property 'javax.xml.validation.SchemaFactory:http://www.w3.org/2001/XMLSchema'
JAXP: The value is 'com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory'
JAXP: createInstance(com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory)
JAXP: loaded com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory from (no code source)
JAXP: factory 'com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory' was found for http://www.w3.org/2001/XMLSchema
因此,在出现错误之前,您将看到JAXP调试日志记录,然后您应该知道您必须为哪个工厂提供实现才能使其工作。