j 在 Rails 中使用 Coffeescript 渲染并了解如何清理 Javascript

j render With Coffeescript in Rails and Understanding How to Sanitize Javascript

  1. 我正在尝试使用 javascript 显示资源的属性。我确定我犯了一个简单的错误或遗漏。

  2. 我正在尝试了解 j render 的工作原理以及它的必要性。我知道这与恶意用户输入 javascript 的场景有关,它会在应用程序中执行,这可能会导致不好的事情发生。

设置:rails 应用中的简单博客模板:rails g scaffold Blog title:string content:text

views/blogs/show.html.erb

<div id="blogContent"> Javascript should enter result of @blogger.content here: </div>

assets/javascripts/blogs.咖啡

$document.on "page:change", ->
    $blogPost = "<%= j render(@blog.content) %>"
    alert($blogPost)
    $('#blogContent').append($blogPost)

以下是我 运行 关注的问题:

  1. 警告框的字面意思是 returning: <%= j render(@blog.content %>。我想要 return 该博客的内容。

  2. 一旦我让它运行到显示博客内容的地方,我想向自己证明有必要转义 javascript 这样恶意用户输入就不会在我的应用。因此,例如,如果恶意用户在内容中输入:<a href='DangerousSite.xyz'>Hacker says click for free stuff</a> 那么我的应用程序呈现 @blog.content 的结果将是一个 link,上面写着:Hacker says click for free stuff。一旦我向自己证明转义 javascript 是防止此类事情的必要条件,我希望能够转义它并让结果字面上显示 <a href="Dangerous Site">Hacker says click for free stuff</a>,或者以其他任何方式呈现消毒 javascript 看起来像。


1. 您可能需要遵循以下提示:
Rails: access controller instance variable in CoffeeScript or JavaScript asset file

2. 如果你要避免 HTML,你应该转义 HTML,从我读过的内容来看,j render 只会转义 Javascript,并防止 运行,但不能阻止 HTML,就像你举的例子一样。

要用 JavaScript 转义 HTML,请使用这样一个方便的函数:

var entityMap = {
"&": "&amp;",
"<": "&lt;",
">": "&gt;",
'"': '&quot;',
"'": '&#39;',
"/": '&#x2F;'
};

function escapeHtml(string) {
    return String(string).replace(/[&<>"'\/]/g, function (s) {
      return entityMap[s];
    });
}

摘自把手:https://github.com/wycats/handlebars.js/blob/0a9fc171b00a12fa990d2f7d27310182ed51a41c/lib/handlebars/utils.js

为了回答关于转义的第一部分 Javascript 让我们看一下这段代码:

$blogPost = "<%= j render(@blog.content) %>"

现在想象一个用户决定用 DHH 的一句话开始他们的博客 post:

“Workaholics don't actually accomplish more than nonworkaholics.” 

现在,由于此上下文中的 Javascript 发生在客户端,因此代码中的 Ruby 将首先被评估。因此,您的 Javascript 现在看起来像这样:

$blogPost = "“Workaholics don't actually accomplish more than nonworkaholics.”"

如您所见,其中有一组额外的引号从字符串中断开。实际引用将被解释器读取为 Javascript,这将中断,因为它是无效的 Javascript。恶意用户可以通过重写他们的博客 post 以包含 Javascript 而不是引用来利用这一点。为了解决这个问题,我们用 j(escape_javascript 的缩写)转义引号,所以:

“Workaholics don't actually accomplish more than nonworkaholics.”

变为:

\&quot;Workaholics don't actually accomplish more than nonworkaholics.\&quot;

现在进入第二部分。您的代码实际上返回 "j render(@blog.content)" 的原因是因为您的那部分代码是 Ruby 并且需要在您的 Javascript 发送到浏览器之前由 ERB 处理。要让 ERB 处理此文件,只需将 .erb 添加到您的文件名中:

assets/javascripts/blogs.coffee.erb

但是,这是一种不好的做法,因为资产中的 Javascript 与您的应用程序处于不同的上下文中,因此我怀疑它不会找到 @blogs 变量。因此,您应该将 blogs.coffee.erb 文件移动到适当的视图文件夹,如下所示:

app/views/blogs/index.coffee.erb

(虽然一旦您将其移至视图中,我相信不再需要 .erb,正如 Rails 暗示的那样)