Mass Assignment 防止Hacked
涉及到一个安全问题,可能有人会利用这个问题进行Hack,加以注意可以避免。
官方说明地址:http://guides.rubyonrails.org/security.html#mass-assignment
Railscasts-china视频地址:http://railscasts-china.com/episodes/mass-assignment?autoplay=true 由Terry Tai进行讲解,个人觉得讲得很不错。学习很多。
这篇文章介绍的方法很不错:http://excid3.com/blog/rails-tip-7-mass-assignment-security/。通过白名单 + params[:user].delete :is_admin 的方式来满足admin对 is_admin这个属性的操作
这里涉及到的文件有:
- config/application.rb
config.active_record.whiltelist_attributes = true
- Model 里的 attr_accessible 与 attr_protected使用
# 黑名单 attr_protected :is_admin # 白名单 attr_accessible :email, :username
- Controller里的 params[:user]使用
问题的产生:
有一个名为User的Model,属性如上所述, 以及相对应的Contorller:UsersContoller。如果把 is_admin属性写在 accessible里,则在填写表单时,在console里把user[email] 改为 user[is_admin],然后填入非0数据,就可以把is_admin的值设置成为 true 。因为在Contoller里我们是这样写的:
File: users_controller.rb
def update if @user.update_attributes(params[:user]) redirect_to @user, notice: 'User was successfully updated.' else render action: "edit" end end
这样也就会全盘地接受传过来的值,导致把 is_admin的值也被更改。
解决办法
综合视频以及其他一些博客给出的方法,有以下几种:
- 黑名单:在Model里,把 is_admin 用 attr_protected进行保护,不被访问到,即黑名单。坏处是不够灵活,会影响到Model的其他的行为
class User < ActiveRecord::Base attr_protected :is_admin end
- 白名单:不把is_admin写在attr_accessible里面,这样也不会被访问到
class User < ActiveRecord::Base attr_accessible :email, :username end
- 在Controller里,对传入的参数进行过滤选择: params[:user].slice(:email, :username),这时Model里面不要把 is_admin 用attr_accessible 来控制。
class UsersController < ApplicationController def create @user = User.find(params[id]) if @user.update_attributes(user_params) redirect_to @user, notice: 'User was successfully updated.' else render action: "new" end end private def user_params params[:user].slice(:email, :username) end end
通过加入一个 user_params 方法,来对传入的参数进行筛选,把 is_admin 排除在外。这种做法好处在于可以灵活定制,但会Repeat Yourself。
总体来说,个人觉得还是在Controller里进行一个安全过滤比较靠谱。
关于白名单:在 config/application.rb 里有一行内容为“config.active_record.whiltelist_attributes = true ”,就是说明,在每一个Model里都要显式地声明一个 attr_accessible,否则会出错。如果不想使用这功能,可以把true 设置为 false