java - 是否可以避免使用 xalan TransformerFactory?
问题描述
我有以下代码:
final TransformerFactory factory = TransformerFactory.newInstance();
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
第二行在具有默认TransformerFactory
. 但是,当我将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)
我猜这是因为 xalanTransformerFactory
不支持这个属性。Xalan 的实现是通过ServiceLoader
机制获取的:它services/javax.xml.transform.TransfomerFactory
在 xalan jar 中指定。
可以TransformerFactory
使用javax.xml.transform.TransformerFactory
系统属性或$JRE/lib/jaxp.properties
文件覆盖实现,或直接在代码中传递类名。但要做到这一点,我必须提供一个具体的类名。现在,它是com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl
,但是在系统属性中硬编码它有点吓人,因为在 JDK 升级时他们可以很容易地更改类名,我们只会得到一个运行时错误。
有什么方法可以指示TransformerFactory.newInstance()
忽略 xalan 提供的实现?或者告诉它“只使用系统默认值”。
PS 我不能只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 工厂类名称是否/何时更改。
推荐阅读
- python - 如何使用 SQLAlchemy 的 to_sql 插入 VARBINARY 列?
- reactjs - reactjs:提供来自不同服务器的资产
- ios - Swift Package 平台是最低版本吗?
- python - 如何在 Python 中创建构建文件或 sh 文件
- android - 如何检查在 Wear OS 3(Samsung Galaxy Watch 4)上运行的应用程序上可用的互联网
- mysql - 如何在 MySQL 中查找和插入丢失的数据而不创建重复数据
- kubernetes - 是否可以在 Mutating Webhook 中修改对象命名空间?
- c# - 与显式类型参数相比,使用“object”参数时的 C# NumSharp 未定义行为
- sql - 使用 declare table 运行聚合查询
- firebase - 将一组对象从 Firebase 映射到 List Flutter