【发布时间】:2010-09-17 23:14:23
【问题描述】:
使用 XmlDocument.Load 时,我发现如果文档引用 DTD,则会与提供的 URI 建立连接。有什么办法可以防止这种情况发生吗?
【问题讨论】:
使用 XmlDocument.Load 时,我发现如果文档引用 DTD,则会与提供的 URI 建立连接。有什么办法可以防止这种情况发生吗?
【问题讨论】:
经过一番挖掘,也许您应该将 XmlReaderSettings 对象的 XmlResolver 属性设置为 null。
'XmlResolver 用于定位和 打开 XML 实例文档,或 找到并打开任何外部资源 由 XML 实例引用 文档。这可以包括实体, DTD 或架构。'
所以代码看起来像这样:
XmlReaderSettings settings = new XmlReaderSettings();
settings.XmlResolver = null;
settings.DtdProcessing = DtdProcessing.Parse;
XmlDocument doc = new XmlDocument();
using (StringReader sr = new StringReader(xml))
using (XmlReader reader = XmlReader.Create(sr, settings))
{
doc.Load(reader);
}
【讨论】:
正在加载的文档有一个 DTD。
与:
settings.ProhibitDtd = true;
我看到以下异常:
服务无法启动。 System.Xml.XmlException:出于安全原因,此 XML 文档中禁止使用 DTD。要启用 DTD 处理,请将 XmlReaderSettings 上的 ProhibitDtd 属性设置为 false,并将设置传递给 XmlReader.Create 方法。
因此,在这种情况下,ProhibitDtd 似乎必须设置为 true。
看起来 ValidationType 可以解决问题,但是:
settings.ValidationType = ValidationType.None;
我仍然看到与 DTD uri 的连接。
【讨论】:
这实际上是 XML 规范中的一个缺陷。 W3C 哀叹人们都疯狂地攻击他们的服务器以加载数十亿次模式。不幸的是,几乎没有标准 XML 库能做到这一点,它们都一遍又一遍地访问服务器。
DTD 的问题特别严重,因为 DTD 可能包含 XML 文件可能实际依赖的一般实体声明(例如& -> &)。因此,如果您的解析器选择放弃加载 DTD,而 XML 使用通用实体引用,则解析实际上可能会失败。
解决此问题的唯一方法是透明缓存实体解析器,它将下载的文件放入库搜索路径中的某个存档中,以便动态创建该存档并几乎自动与任何软件分发捆绑在一起。但即使在 Java 世界中,也没有一个像样的 EntityResolver 浮动,肯定不是 apache 基金会内置的。
【讨论】:
试试这样的:
XmlDocument doc = new XmlDocument();
using (StringReader sr = new StringReader(xml))
using (XmlReader reader = XmlReader.Create(sr, new XmlReaderSettings()))
{
doc.Load(reader);
}
这里要注意的是 XmlReaderSettings 的 ProhibitDtd 属性默认设置为 true。
【讨论】:
使用XMLReader 加载文档并将阅读器设置的ValidationType 属性设置为None。
【讨论】: