我正在编写一个带有 AngularJS 前端的 rails 应用程序,这是我正在编写的关于连接 rails 和 angularjs的教程系列的一部分。这意味着我的 Rails 应用程序仅以 JSON 格式与浏览器通信。
在angularjs $http 文档中,它描述了一个潜在的 json 安全漏洞,其中 json 请求可以嵌入到脚本标签中,加上一些棘手的 jsonp 使用,以允许类似于跨站点脚本攻击的东西。我发现了其他几页,特别是我认为描述得很好的一页,并且可以追溯到 2008 年,所以这不是一个新问题。
显然,这不是标准 rails json 渲染中的漏洞,因为 rails 默认提供包含数组的对象。但是在使用 angularjs 时,我们似乎设置了 root: false (虽然我不得不承认我找不到我这样做的地方,但它绝对没有给出根节点)。
无论如何,底线是角度文档建议在任何 json 响应前面加上 )]}',所以:
['one','two']
变成
)]}',
['one','two']
然后,Angular 会再次自动将其剥离。
我正在寻找一种优雅地做到这一点的方法。我在 stackoverflow 上看到了很多关于此的问题和答案,但其中大多数要么与更早版本的 rails 相关,在 JSON 处理被更彻底地嵌入之前,要么似乎需要我创建大量样板代码。我正在寻找一种可以应用于应用程序控制器的方法,或者作为一种辅助方法,它可以在任何地方工作。
我目前使用的控制器如下所示:
class ClubsController < ApplicationController
respond_to :json
# GET /clubs.json
def index
@clubs = Club.all
render json: @clubs
end
end
这不会调用任何模板 - 渲染操作会跳过模板引擎。我可以通过将渲染线改为:
respond_with json: @clubs
并创建一个模板文件views/clubs/index.json.erb,其中包含
)]}',
<%= raw(@clubs.to_json) %>
但是我必须为每个控制器上的每个动作创建一个模板,这感觉就像样板。我希望能够将视图/布局/application.json.erb 更改为:
)]}',
<%= yield %>
但这不起作用,因为我们只有在调用 respond_with 时才能得到模板。如果我们调用respond_with,我们无法将@clubs 放入响应中——所以我们最终得到:
)]}',
作为整个响应。
另一种选择可能是覆盖 as_json 方法来添加我想要的东西,但这似乎有点像大锤。理想情况下,我可以在某个地方引入辅助方法,例如:
render prepend_vulnerability_protection(json: @clubs)
所以,毕竟,有两个问题:
- 这甚至是一个真正的问题,还是 Rails 已经有了其他保护,这意味着我根本不需要担心这个
- 有没有办法集中执行此操作,还是我需要硬着头皮创建所有样板模板?我可以修改脚手架生成器来做到这一点,所以这不是世界末日,但它看起来确实像很多样板代码