Javascript Rails:如何使用客户端AJAX请求转义Java脚本

Javascript Rails:如何使用客户端AJAX请求转义Java脚本,javascript,jquery,ruby-on-rails,ruby,ajax,Javascript,Jquery,Ruby On Rails,Ruby,Ajax,当我通过将集合从控制器操作直接从客户端发送到_json时,如何转义集合 当我说请求从控制器操作发送,然后直接发送到客户端(跳过预处理)时,看起来是这样的: AJAX请求被路由到控制器操作 控制器操作通过javascript直接将结果发送给请求者,请求者的javascript将在客户端进行处理。类似于:app/assets/javascripts/blogs.js 这与将请求发送到控制器_操作,然后发送到服务器端视图进行预处理,然后将结果发送到请求者不同。看起来像这样: AJAX请求 路由

当我通过
将集合从控制器操作直接从客户端发送到_json
时,如何转义集合

  • 当我说请求从控制器操作发送,然后直接发送到客户端(跳过预处理)时,看起来是这样的:

    • AJAX请求被路由到控制器操作
    • 控制器操作通过javascript直接将结果发送给请求者,请求者的javascript将在客户端进行处理。类似于:
      app/assets/javascripts/blogs.js
  • 这与将请求发送到控制器_操作,然后发送到服务器端视图进行预处理,然后将结果发送到请求者不同。看起来像这样:

    • AJAX请求
    • 路由到控制器操作
    • 发送到视图进行预处理。类似于:
      app/views/blogs/index.js.erb
    • 结果将发送给请求者
简短示例:

def some_action
  @blogs = Blog.all
  respond_to do |format|
    format.json {render json: @blogs} # currently dangerous, @blogs is not sanitized.
  end
end
例如:假设该集合中的一个
@blog
记录有黑客输入的数据:

@blogs.first.title
  => <script>alert('Site now hacked if this javascript runs!')</script>

上面:我关心的部分是
value.id
value.title
。如果我不逃脱,这些事情可能会很危险。我想确保它被转义,这样任何危险的输入都将变得无害。

您正在处理一个未初始化的HTML字符串,就像其他字符串一样。在将其插入页面之前,您需要确保其安全。您真正需要做的就是将
字符替换为

以该控制器为例:

class SomethingController < ApplicationController
  def jsontest
    render json: { blogs: ["<script>alert(1);</script>"] }
  end
end
class-SomethingController
如果您不介意笨重,jQuery可以为您做到这一点:

$.ajax({
  type: 'GET',
  url: '/something/jsontest', 
  dataType: 'json',
  success: function (data) { 
    console.log($('<div>').text(data['blogs'][0]).html()); 
  }
})

> &lt;script&gt;alert(1);&lt;/script&gt;
$.ajax({
键入:“GET”,
url:“/something/jsontest”,
数据类型:“json”,
成功:函数(数据){
console.log($('').text(数据['blogs'][0]).html();
}
})
>脚本警报(1)/剧本

您还可以在控制器端使用
ActionView::Helpers::SanitizeHelper#sanitize
,这将删除它找到的任何HTML标记。(通常这只对视图可用,因此您可以创建一个视图来呈现JSON,也可以在控制器中包含ActionView::Helpers::SanitizeHelper
)。或者两者都做

下面是一个解决方案。请记住,在数据被持久化到数据库之前对其进行清理通常是个好主意。另外:最好在向请求者发送响应之前对服务器端进行清理:

app/assets/javascripts/blogs.js

$("body").on('change', '[data-action="blogger_sel"]', function() {
  var blogs_selection = $(this).closest('[data-parent-for="blogs_sel"]').find('[data-action="blogs_sel"]');
  $.ajax({
    url: "/blogs",
    type: "GET",
    data: {blogger_id: $(this).val()},
    success: function (data) {
      blogs_selection.children().remove();
      $.each(data, function (index, item) {
        blogs_selection.append('<option value=' + item.id + '>' + item.title + '</option>');
       });
     }
   })
 });
$("body").on('change', '[data-action="blogger_sel"]', function() {
  var blog_sel = $(this).closest('[data-parent-for="blog_sel"]').find('[data-action="blog_sel"]');
  $.ajax({
    url: "/blogs",
    type: "GET",
    data: {blogger_id: $(this).val()},
    success: function (data) {
      blog_sel.children().remove();
      $.each(data, function (index, item) {
        blog_sel.append($('<option>', {
          value: item.id,
          text : item.title
        }));
      });
    }
  })
});
$(“body”)。关于('change','data action=“blogger_sel”]”,函数(){
var blog_sel=$(this).closest(“[data parent for=“blog_sel”]”)。find(“[data action=“blog_sel”]”);
$.ajax({
网址:“/blogs”,
键入:“获取”,
数据:{blogger_id:$(this.val()},
成功:功能(数据){
blog_sel.children().remove();
$。每个(数据、功能(索引、项目){
博客选择附加($(''){
值:item.id,
文本:item.title
}));
});
}
})
});
不要以以下方式附加选项,因为它将执行危险的黑客攻击:

blogs_selection.append('<option value=' + value.id + '>' + value.title + '</option>');
blogs\u selection.append(“”+value.title+“”);

谢谢您的回答。我试图让它为我的例子工作,但我有困难。为了尝试应用您的解决方案:显示:
value.title
,我尝试将您的客户端设置为:
value.title.html()
,但它似乎不起作用。您需要这样做:
$('').text(value.title.html())
重要的部分是通过jQuery在内存中创建
div
对象。