我有以下代码:
final TransformerFactory factory = TransformerFactory.newInstance();
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
第二行在带有默认
TransformerFactory
的现代JDK(我尝试过1.8)中运行良好。但是,当我将xalan
(最新的版本2.7.2)添加到类路径时,在第二行得到以下内容: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
机制实现的:它是在xalan jar中的services/javax.xml.transform.TransfomerFactory
中指定的。可以使用
TransformerFactory
系统属性或javax.xml.transform.TransformerFactory
文件覆盖$JRE/lib/jaxp.properties
实现,也可以直接在代码中传递类名。但是要做到这一点,我必须提供一个具体的类名。现在,它是com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl
,但是在系统属性中对其进行硬编码有点吓人,因为在JDK升级中,它们可以轻松更改类名,而我们只会遇到运行时错误。有什么方法可以指示
TransformerFactory.newInstance()
忽略xalan提供的实现吗?或告诉它“仅使用系统默认值”。P.S.我不能只从类路径中删除
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工厂类名称是否更改/何时更改。
关于java - 是否可以避免使用xalan TransformerFactory?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50000756/