首先,一些背景知识。
什么是 DTD?
您尝试解析的文档包含文档类型声明;如果您查看该文档,您会在开头附近发现一系列以<!DOCTYPE
并以相应的结尾>
。这样的声明允许 XML 处理器根据一组声明来验证文档,这些声明指定一组元素和属性并限制它们可以具有的值或内容。
由于实体也在 DTD 中声明,因此 DTD 允许处理器知道如何扩展对实体的引用。 (实体pubdate
可以定义为包含文档的发布日期,例如“2012 年 12 月 15 日”,并在文档中多次引用为&pubdate;
-- 由于在实体声明中实际日期仅给出一次,因此这种用法可以更轻松地保持文档中对发布日期的各种引用彼此一致。)
DTD 是什么意思?
文档类型声明具有纯粹的声明性含义:按照 XML 规范中定义的语法,可以在某处找到此文档类型的模式。
有些软件是由对 XML 基础知识掌握较弱的人编写的,他们对声明的含义存在基本的混淆。它假设文档类型声明的含义不是陈述性的(那里有一个模式)但是至关重要的(请验证此文件)。您正在使用的解析器似乎就是这样的解析器;它假定通过向其提供具有文档类型声明的 XML 文档,您已请求某种处理。其作者可能会受益于有关如何接受用户的运行时参数的补习课程。 (您会发现,对于某些人来说,理解声明性语义是多么困难:甚至某些 XML 解析器的创建者有时也无法理解它们,而是陷入了命令式思维。唉。)
他们所说的“安全原因”是什么?
一些具有安全意识的人认为 DTD 处理(验证或未经验证的实体扩展)构成安全风险。使用实体扩展,可以轻松创建非常小的 XML 数据流,当所有实体完全扩展时,该数据流将扩展为非常大的文档。如果您想了解更多信息,请搜索有关所谓“十亿笑声攻击”的信息。
防止十亿笑声攻击的一种明显方法是,对于那些对用户提供的或不受信任的数据调用解析器的人来说,在限制允许解析过程消耗的内存量或时间的环境中调用解析器。自 20 世纪 60 年代中期以来,此类资源限制一直是操作系统的标准部分。然而,由于我仍然不清楚的原因,一些具有安全意识的人认为正确的答案是在不受信任的输入上运行解析器无资源限制,显然相信只要您无法根据商定的模式验证输入,这就是安全的。
这就是为什么您的系统告诉您您的数据存在安全问题。
对于某些人来说,DTD 是一种安全风险的想法听起来更像是偏执而不是理智,但我不认为它们是正确的。请记住 (a) 健康的偏执是安全专家在生活中所需要的,并且 (b) 任何真正对安全感兴趣的人在任何情况下都会坚持资源限制——在解析过程存在资源限制的情况下,DTD 是无害。禁止 DTD 并不是偏执而是拜物教。
现在,随着背景的消失......
你如何解决这个问题?
最好的解决方案是向您的供应商强烈抱怨他们被有关 XML 安全性的老太太的故事所欺骗,并告诉他们如果他们关心安全性,他们应该进行合理的安全分析而不是禁止 DTD。
同时,正如消息所示,您可以“将 XmlReaderSettings 上的 ProhibitDtd 属性设置为 false,并将设置传递到 XmlReader.Create 方法中”。如果输入实际上不受信任,您还可以考虑为进程提供适当的资源限制的方法。
作为后备(我不推荐这样做),您可以注释掉输入中的文档类型声明。