【问题标题】:Prevent DTD download when parsing XML解析 XML 时阻止 DTD 下载
【发布时间】:2010-09-17 23:14:23
【问题描述】:

使用 XmlDocument.Load 时,我发现如果文档引用 DTD,则会与提供的 URI 建立连接。有什么办法可以防止这种情况发生吗?

【问题讨论】:

    标签: c# .net xml


    【解决方案1】:

    经过一番挖掘,也许您应该将 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);
                }
    

    【讨论】:

    • 还需要的是:settings.ProhibitDtd = false;否则,就在钱上。干杯!
    • 这是一个有用的技巧,但请记住,它不适用于所有 XML 文档。如果文档实际上以某种方式引用了 DTD(例如实体引用),那么当您尝试读取该文档时会出现 XML 异常。
    • 我试过这个,也发现它有效,但是我对 MSDN 文档中的这条评论有点困扰:“如果设置为 null,当 XmlReader 尝试访问外部时会抛出 XmlException资源”。这显然没有发生,但有人知道为什么吗?有人愿意对此发表评论吗?
    • 经过一些实验,我发现将Processing设置为Parse仍然可以获取DTD。这成功了,并阻止它对我来说很愚蠢:XmlReaderSettings settings = new XmlReaderSettings {DtdProcessing = DtdProcessing.Ignore};
    【解决方案2】:

    正在加载的文档有一个 DTD。

    与:

    settings.ProhibitDtd = true;
    

    我看到以下异常:

    服务无法启动。 System.Xml.XmlException:出于安全原因,此 XML 文档中禁止使用 DTD。要启用 DTD 处理,请将 XmlReaderSettings 上的 ProhibitDtd 属性设置为 false,并将设置传递给 XmlReader.Create 方法。

    因此,在这种情况下,ProhibitDtd 似乎必须设置为 true。

    看起来 ValidationType 可以解决问题,但是:

    settings.ValidationType = ValidationType.None;
    

    我仍然看到与 DTD uri 的连接。

    【讨论】:

      【解决方案3】:

      这实际上是 XML 规范中的一个缺陷。 W3C 哀叹人们都疯狂地攻击他们的服务器以加载数十亿次模式。不幸的是,几乎没有标准 XML 库能做到这一点,它们都一遍又一遍地访问服务器。

      DTD 的问题特别严重,因为 DTD 可能包含 XML 文件可能实际依赖的一般实体声明(例如& -> &)。因此,如果您的解析器选择放弃加载 DTD,而 XML 使用通用实体引用,则解析实际上可能会失败。

      解决此问题的唯一方法是透明缓存实体解析器,它将下载的文件放入库搜索路径中的某个存档中,以便动态创建该存档并几乎自动与任何软件分发捆绑在一起。但即使在 Java 世界中,也没有一个像样的 EntityResolver 浮动,肯定不是 apache 基金会内置的。

      【讨论】:

        【解决方案4】:

        试试这样的:

        XmlDocument doc = new XmlDocument();
        using (StringReader sr = new StringReader(xml))
          using (XmlReader reader = XmlReader.Create(sr, new XmlReaderSettings()))
          {
             doc.Load(reader);
          }
        

        这里要注意的是 XmlReaderSettings 的 ProhibitDtd 属性默认设置为 true。

        【讨论】:

          【解决方案5】:

          使用XMLReader 加载文档并将阅读器设置的ValidationType 属性设置为None。

          【讨论】:

          • 不幸的是,如果 XML 使用 DTD 中定义的实体引用,那将无济于事,因为这会使 XML 格式不正确,并非无效。
          • 所以,我觉得有必要处理 DTD 以便正确处理实体引用。但是,如果没有连接,这将如何工作?
          • 不会。如果您的文档可以包含在 DTD 中定义的实体引用,则解析器需要该 DTD。因此,您必须在尝试解析的 XML 中包含 DTD,或者在本地缓存 DTD。这是我不喜欢使用实体引用的原因之一。
          猜你喜欢
          • 2013-02-08
          • 2013-06-08
          • 2016-04-23
          • 2023-03-22
          • 1970-01-01
          • 2014-09-28
          • 2010-09-23
          • 2017-07-01
          • 2017-08-19
          相关资源
          最近更新 更多