【问题标题】:Store html entities in database? Or convert when retrieved?将html实体存储在数据库中?还是在检索时转换?
【发布时间】:2009-12-28 18:36:50
【问题描述】:

快速提问,在将数据插入数据库之前还是之后调用htmlentities()(或htmlspecialchars())是否更好?

之前:新的更长的字符串将导致我不得不更改数据库以在字段中保存更长的值。 (maxlength="800" 可以更改为 804 字符字符串)

之后:这将需要更多的服务器处理,并且在每次页面加载或 AJAX 加载时可能会调用数百次 htmlspecialchars()

太棒了。检索结果时进行转换会显着减慢我的代码吗?我应该更改数据库吗?

【问题讨论】:

    标签: php mysql


    【解决方案1】:

    我建议将最原始的数据形式存储在数据库中。在选择输出数据的方式和位置时,这为您提供了最大的灵活性。

    如果您发现性能存在问题,您可以以某种方式缓存此数据的 HTML 格式版本。请记住,过早的优化是一件坏事。

    【讨论】:

    • 我会喝凉水的。但我真的希望它不会太慢。也许我只是偏执,你对过早优化是对的。
    • 我发现当你的数据库中有大量 & 时,这是一个巨大的痛苦。那么每个查询或搜索都必须具有相同的格式。
    【解决方案2】:

    我没有 php 的经验,但通常我总是转换或转义最接近输出。您不知道您的输出要求何时会发生变化,例如您可能希望将数据输出为 XML 或 JSON 数组,因此转义为 HTML 然后存储意味着您只能将数据用作 HTML。

    【讨论】:

    • 糟糕.. 起初我以为您是在提倡将 HTML 放入数据库中(“HTML 输出”与“输出”)。我想我们说的是同一件事。
    【解决方案3】:

    在 php/MySQL Web 应用程序中,数据以两种方式流动

    数据库 -> 脚本语言 (php) -> HTML 输出 -> 浏览器 -> 屏幕 和 键盘 -> 浏览器 -> $_POST -> php -> SQL 语句 -> 数据库。

    数据被定义为用户提供的一切。

    总是总是总是......

    A) 在将数据移入 SQL 语句时通过 mysql_real_escape_string 处理数据,并且

    B) 在您将数据移入 HTML 输出时,通过 htmlspecialchars 处理数据。

    这将保护您免受 sql 注入攻击,并使 html 字符和实体能够正确显示(除非您设法忘记了一个地方,然后您打开了一个安全漏洞)。

    我是否提到必须对任何用户可能通过脚本触摸、更改或提供的每条数据都执行此操作?

    附言出于性能原因,请在任何地方使用 UTF-8 编码。

    【讨论】:

    • 已经在做这三个 :)) 但是在你的大脑中重新执行良好的练习永远不会有坏处。向上+
    • 请注意,这个答案现在已经很老了。 mysql_* 函数现在不应使用 PDOprepared requests
    【解决方案4】:

    最好将文本存储为原始文本并根据需要对其进行编码,老实说,当您将数据输出到 wbe 页面时,您总是需要对数据进行 htmlencode 以防止 XSS 黑客攻击。

    您不应该在将数据放入数据库之前对其进行编码。主要原因是:

    1. 如果此类数据接近列大小限制,例如 32 个字符,如果标题是“Steve & Fred blah blah”,那么您可能会超过该列限制,因为 1 char & 变成 5 char & amp;李>
    2. 您假设数据将始终显示在网页中,将来您永远不知道将在哪里查看数据并且您可能不希望对其进行编码,现在您必须对其进行解码,并且您可能可能无法访问 PHP 的解码函数

    【讨论】:

      【解决方案5】:

      “两次测量,一次优化”是工匠之道。

      【讨论】:

      • 或更常见的“测量一次,不优化”
      【解决方案6】:

      如果您的网站不需要高性能,请将其存储为原始数据,并在输出时执行您想要的操作。
      如果您需要性能,请考虑将其存储两次:原始数据以执行您想要的操作,另一个字段包含过滤后的数据。可以看作是冗余的,但是 CPU 很贵,而数据存储真的很便宜。

      【讨论】:

      • 从来没想过。我已经承诺了这个项目(它是在线的,我不想惹它XD)但将来会考虑这个
      • 这很重要,“CPU 很贵,而数据存储真的很便宜。”谢谢
      【解决方案7】:

      最简单的方法是“按原样”存储数据,然后在需要的地方转换为 htmlentities。

      最安全的解决方案是在数据进入数据库之前对其进行过滤,因为这样可以防止由于缺乏安全实施而可能对您的服务器和数据库进行的攻击,然后在需要时根据需要进行转换。此外,如果您使用 PDO,这将自动为您使用准备好的语句发生。

      http://php.net/PDO

      【讨论】:

        【解决方案8】:

        我们最近在工作中进行了这场辩论。我们决定将转义值存储在数据库中,因为之前(当我们未转义存储它时)存在一些极端情况,即显示数据而没有转义。这可能导致 XSS。因此,我们决定将其转义存储以确保安全,如果您想要它未转义,您必须自己完成这项工作。

        编辑:所以对于不同意的每个人,让我为我的案例添加一些背景故事。假设您在一个 50 多人的团队中工作......并且不能保证数据库中的数据在输出时是 HTML 编码的 - 没有内置机制,因此开发人员必须编写代码去做吧。而且这些数据到处都显示,所以它不是经过 1 个开发人员的代码,而是经过 30 年代的 - 大多数人对这些数据一无所知(或者它甚至可能包含很少见的尖括号),只是想得到它显示在页面上,继续前进,然后忘记它。

        您是否仍然认为将数据以 HTML 格式放入数据库中并依靠不是您的随机人员来正确处理事情会更好?因为坦率地说,虽然它看起来肯定不是温暖的模糊最佳实践,但我更喜欢失败关闭(这意味着当数据在 Word Doc 中出现时,它看起来像 Value

        【讨论】:

        • 非常个坏建议。也许周围有太多草率的代码让您无法选择;但总的来说这是错误的做法。
        • 我将修复允许显示未转义用户输入的过程。
        • 这在一般情况下是完全错误的,因为其他人在他们的答案中已经指出了原因。你最终会得到一个充满垃圾的数据库。
        • 对于 XSS,我认为存储已清理的数据和存储已转义的数据之间存在巨大的混淆。您希望存储已清理但未转义的数据。
        • 如果您有 30 名开发人员对 XSS 和逃逸实践一无所知,那么您将面临严重的招聘和/或培训问题。
        猜你喜欢
        • 1970-01-01
        • 2017-09-09
        • 2021-10-23
        • 2014-12-30
        • 2014-09-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-21
        相关资源
        最近更新 更多