Rails Rails 4.1.5 开始 where 查询也有类似 Mass Assignment 保护了

reyesyang · 2014年09月15日 · 最后由 sg552sg552 回复于 2014年10月02日 · 4842 次阅读
本帖已被管理员设置为精华贴

前两天将项目中的 Rails 生到了 4.1.5,跑了测试发现有几个查询相关的用例抛出了 ActiveModel::ForbiddenAttributesError 的异常,这个异常大家很熟悉,是防止 Mass Assignment 而在 Rails 4 中引入的一种保护机制。但是常用在创建或更新对象的逻辑中,突然在查询相关逻辑中抛出这样的异常,还是有些莫名奇妙。

根据异常栈查看类 Rails 的源码,发现 4.1.5 where 查询确实进行了更新,新增了 opts = sanitize_forbidden_attributes(opts) 这步,而 sanitize_forbidden_attributes 本身就是 sanitize_for_mass_assignment 方法的别名。如下:

Rails 4.1.5

# https://github.com/rails/rails/blob/v4.1.5/activerecord/lib/active_record/relation/query_methods.rb#L563
def where!(opts = :chain, *rest) # :nodoc:
  if opts == :chain
    WhereChain.new(self)
  else
    if Hash === opts
      opts = sanitize_forbidden_attributes(opts)
      references!(PredicateBuilder.references(opts))
    end

    self.where_values += build_where(opts, rest)
    self
  end
end

# https://github.com/rails/rails/blob/v4.1.5/activemodel/lib/active_model/forbidden_attributes_protection.rb#L26
alias :sanitize_forbidden_attributes :sanitize_for_mass_assignment

Rails 4.1.4

# https://github.com/rails/rails/blob/v4.1.4/activerecord/lib/active_record/relation/query_methods.rb#L560
def where!(opts = :chain, *rest) # :nodoc:
  if opts == :chain
    WhereChain.new(self)
  else
    references!(PredicateBuilder.references(opts)) if Hash === opts

    self.where_values += build_where(opts, rest)
    self
  end
end

根源找到了,就比较好修复。将原代码中的 conditions = params.slice(:ua, :sdk) 改为 conditions = params.permit(:ua, :sdk)。其实两者的目的是一样的,防止用户自己构造表单查询本没有权限查看的内容。所以 Rails 也算是强制统一了读写操作中对 params 的限制措施。

哇 羊厉害,领教了

这点很好,强制开发者去考虑 Strong Params 的问题。

赞,,先驱啊

之前遇到过,算是小小的坑,升级到 4.1.5 的都要注意检查跟跑测试了。

刚刚升级到 4.1.5,暂时没有遇到楼主的问题。

前两天刚遇到这个问题。

正准备升级呢,赞

赞海龙~~~~

需要 登录 后方可回复, 如果你还没有账号请 注册新账号