【问题标题】:Preventing HTML character entities in locale files from getting munged by Rails3 xss protection防止语言环境文件中的 HTML 字符实体被 Rails3 xss 保护破坏
【发布时间】:2011-03-29 11:56:10
【问题描述】:

我们正在构建一个应用程序,这是我们第一次使用 Rails 3,我们必须从一开始就构建 I18n。作为完美主义者,我们希望在视图中使用真正的排版:破折号、弯引号、省略号等。

这意味着在我们的 locales/xx.yml 文件中我们有两个选择:

  1. 内联使用真正的 UTF-8 字符。 应该可以工作,但很难输入,并且 让我害怕,因为数量 仍然顽皮的软件 要 unicode 的东西。
  2. 使用 HTML 字符实体 (’ —等等)。更容易打字, 并且可能更兼容 行为不端的软件。

我宁愿选择第二个选项,但是 Rails 3 中的自动转义使这成为问题,因为 YAML 中的 & 符号本身会自动转换为字符实体,从而导致浏览器中的“可见”&8217;s .

显然,这可以通过在字符串上使用 raw 来解决,即:

raw t('views.signup.organisation_details')

但我们并不乐意每次t 时都走全局raw-ing 的路线,因为这会让我们容易出错并产生XSS 漏洞。

我们可以选择性地raw 知道包含字符实体的字符串,但这很难扩展,而且感觉不对 - 此外,包含一种语言实体的字符串可能不包含另一种语言。

关于解决这个问题的聪明的 rails-y 方法有什么建议吗?还是我们注定要浪费排版、xss 漏洞、浪费时间或所有这些?

【问题讨论】:

  • 这是个好问题。期待一个好的答案。

标签: html ruby-on-rails internationalization ruby-on-rails-3 xss


【解决方案1】:

这个问题有一个ticket in lighthouse,解决方法是在locales/xx.yml文件的i18n键上追加_html,使用t别名1 表示一个 html_safe 字符串。例如:

en:
  hello: "This is a string with an accent: ó"

变成:

en:
  hello_html: "This is a string with an accent: ó"

它会创建以下输出:

这是一个带重音符号的字符串:ó

这将使您不必编写raw t('views.signup.organisation_details') 并导致更清晰的输出:t('views.signup.organisation_details_html')。虽然将raw 换成_html 似乎不是最好的交易,但它确实清楚地表明您正在输出假定为html_safe 字符串的内容。


1 我已经测试了灯塔票中建议的代码。我发现您必须专门使用 t 别名。如果您使用I18n.tI18n.translate,则翻译不会将_html 视为html_safe:
I18n.t('hello_html') 
I18n.translate('hello_html') 
# Produces => "This is a string with an accent: ó"

t('hello_html')      
# Produces => "This is a string with an accent: ó"

我认为这不是 RoR TranslationHelper documentation 的预期行为。

【讨论】:

    【解决方案2】:

    嗯。由于 i18n 的角度,我昨天为这个问题添加了书签,但没有回答它,因为我是一个从未使用过 Rails 的 Python 人。我仍然不打算回答这个问题,但考虑到你没有被乐于助人的 Railsians 淹没,他们可以为你指出绕过 Rails 内部问题的好方法,这仍然是我的观点。

    首先,我认为很棒你从一开始就考虑这个问题。这是相当罕见的。其次,我完全同意使用原始字符串或选择性地选择带有实体的字符串来对听起来像脆弱、丑陋、容易出错的 hack 进行特殊处理。

    现在,如果我正确理解 Rails(我读过 this i18n guide),YAML 文件包含每种语言的本地化字符串。在这种情况下,我强烈建议在其中使用常规字符(在 UTF-8 中)。否则,维护本地化,甚至阅读翻译文件——想想非拉丁脚本中的语言! ——将是地狱。

    是的,这意味着您必须弄清楚输入法,但解决方案简洁明了。

    【讨论】:

    • 是的,只需将完整的 UTF-8 编码字符放入文件中即可。这是自恐龙时代以来 Java 人一直在做的事情 - 查看他们所有的语言 .properties 文件,您会看到本机编码。
    • 回想起来,我认为这可能是最好的解决方案。我不知道为什么我在 3 年前如此反感它。
    【解决方案3】:

    我认为使用“原始”不是一个好主意,您可以尝试使用这样的 yml 字符串

    en:
      hello:
        This generates a text paragraph for HTML. " " à @ ' All this text, which you can find in
        these lines, is being concatenated together to one single text node, and then put
        into the body of the <p> ... </p> tag. ↂↀऊᎣᏍᏮ⁜℺℻⊛⍟⎬⎨⏏♞♝⚫⚬✱✰✭❺❻➣➱➲⬡⬕
    

    HTML

    This generates a text paragraph for HTML. &quot; &quot; à @ ' All this text, which you can find in these lines, is being concatenated together to one single text node, and then put into the body of the &lt;p&gt; ... &lt;/p&gt; tag. ↂↀऊᎣᏍᏮ⁜℺℻⊛⍟⎬⎨⏏♞♝⚫⚬✱✰✭❺❻➣➱➲⬡⬕
    

    浏览器视图

    This generates a text paragraph for HTML. " " à @ ' All this text, which you can find in these lines, is being concatenated together to one single text node, and then put into the body of the <p> ... </p> tag. ↂↀऊᎣᏍᏮ⁜℺℻⊛⍟⎬⎨⏏♞♝⚫⚬✱✰✭❺❻➣➱➲⬡⬕
    

    【讨论】:

      【解决方案4】:

      如果您不想通过简单地将 .html_safe(通过 alias_method_chain 或 w/e)添加到所有内容来暴露错误的可能性,最好的解决方案就是在必要时使用它。

      在我们的网站中,我们使用标记语言从 i18n 语言环境文件中获取 HTML 输出,因为翻译这些文件的人不是开发人员,只是翻译人员。

      如果只在少数几个地方需要您的 HTML 真正成为 HTML,请使用 .html_safe

      t('views.signup.organisation_details').html_safe
      

      我们拥有的简单标记语言非常适合我们,但这确实是针对特定情况的:)

      【讨论】:

        【解决方案5】:

        你知道可以在助手中使用的 html_safe 方法吗?我不确定我是否完全理解这里的问题,因为我从未使用过 I18n,但是是否可以使用自定义帮助程序来确定字符是否不应该被转义并返回“string”.html_safe,以及是否应该被转义,返回“字符串”。

        或者可能覆盖 "t" 助手并添加您的转义逻辑条件 + .html_safe

        【讨论】:

        • 我自己(以及“Rails 方式”)对这个问题的了解不够多,不知道这是一个好的计划还是另一条毁灭之路,但感谢您的想法......可能会尝试把它拿出来,让你知道它是怎么回事。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-04
        • 2021-10-17
        相关资源
        最近更新 更多