Java 是否可以避免使用xalan TransformerFactory?

Java 是否可以避免使用xalan TransformerFactory?,java,xml,xalan,Java,Xml,Xalan,我有以下代码: final TransformerFactory factory = TransformerFactory.newInstance(); factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); 第二行代码在现代JDK(我尝试了1.8)中使用默认的TransformerFactory运行良好。但是,当我将xalan(版本2.7.2,最新版本)添加到classpath时,我在第二行得到了以下信息: Exception

我有以下代码:

final TransformerFactory factory = TransformerFactory.newInstance();

factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
第二行代码在现代JDK(我尝试了1.8)中使用默认的
TransformerFactory
运行良好。但是,当我将
xalan
(版本2.7.2,最新版本)添加到classpath时,我在第二行得到了以下信息:

Exception in thread "main" java.lang.IllegalArgumentException: Not supported: http://javax.xml.XMLConstants/property/accessExternalDTD
    at org.apache.xalan.processor.TransformerFactoryImpl.setAttribute(TransformerFactoryImpl.java:571)
    at Main.main(Main.java:11)
我猜这是因为xalan的
TransformerFactory
不支持此属性。Xalan的实现是通过
ServiceLoader
机制获取的:它在XalanJAR中的
services/javax.xml.transform.TransformerFactory
中指定

可以使用
javax.xml.transform.TransformerFactory
系统属性或
$JRE/lib/jaxp.properties
文件覆盖
TransformerFactory
实现,或者直接在代码中传递类名。但要做到这一点,我必须提供一个具体的类名。现在,它是
com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl
,但是在系统属性中硬编码它有点可怕,因为在JDK升级中,它们可以轻松更改类名,我们只会得到一个运行时错误

是否有任何方法可以指示TransformerFactory.newInstance()忽略xalan提供的实现?或者告诉它“只使用系统默认值”


另外,我不能仅仅从类路径中删除xalan,因为我们使用的许多其他库都依赖于它。

在这里,我唯一能做到的就是对JDK默认工厂进行硬编码,并使用正常的发现过程作为后备:

TransformerFactory factory;
try {
   //the open jdk implementation allows the disabling of the feature used for XXE
    factory = TransformerFactory.newInstance("com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl", SecureXmlFactories.class.getClassLoader());
} catch (Exception | TransformerFactoryConfigurationError e) {
    //this part uses the default implementation of in xalan 2.7.2
   LOGGER.error("Cannot load default TransformerFactory, le's try the usual way", e);
   //not advisable if you dont want your application to be vulnerable. If needed you can put null here.
   factory = TransformerFactory.newInstance();

}
然后在
try/catch

// this works everywhere, but it does not disable accessing
// external DTDs... still enabling it just in case
try {
    factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
} catch (TransformerConfigurationException e) {
    LOGGER.error("Cannot enable secure processing", e);
}

// this does not work in Xalan 2.7.2
try {
    factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
} catch (Exception e) {
    LOGGER.error("Cannot disable external DTD access", e);
}
// this does not work in Xalan 2.7.2
try {
    factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
} catch (Exception e) {
    LOGGER.error("Cannot disable external stylesheet access", e);
}

并监视日志,查看默认JDK工厂类名是否/何时更改。

定义要加载哪个TransformerFactory实现的另一种方法是设置
javax.xml.transform.TransformerFactory
系统属性()

在Ant中,您可以在目标内部执行以下操作:



在上面的示例中,我将OpenJDK8中的一个设置为默认值

是否尝试禁用此功能?如果是,请看这里:@trappski是的,我正在尝试禁用外部DTD处理,因此我的问题看起来像是X/Y问题。但是
factory.setFeature(xmlcontents.FEATURE\u SECURE\u PROCESSING,true)
并不能阻止Xalan访问外部DTD:当我使用外部DTD链接(http链接)向XML提供数据时,Xalan尝试加载该DTD并获得一个
ConnectException
。请注意catch block
factory=TransformerFactory.newInstance()中的实现。它不是XXE安全的,如果受到攻击,此逻辑将失败。请告诉我们使用SecureXmlFactorys.class文件的jar文件名。@ParameshKorrakuti
SecureXmlFactorys
是包含作为建议解决方案显示的代码的类的名称。您可以使用这里显示的代码段,类名并不重要。