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这个属性的操作

这里涉及到的文件有:

  1. config/application.rb
    config.active_record.whiltelist_attributes = true 
  2. Model 里的 attr_accessible 与 attr_protected使用
    # 黑名单
    attr_protected :is_admin
    
    # 白名单
    attr_accessible :email, :username 
  3. 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的值也被更改。

解决办法

综合视频以及其他一些博客给出的方法,有以下几种:

  1. 黑名单:在Model里,把 is_admin 用 attr_protected进行保护,不被访问到,即黑名单。坏处是不够灵活,会影响到Model的其他的行为
    class User < ActiveRecord::Base
      attr_protected :is_admin
    end 
  2. 白名单:不把is_admin写在attr_accessible里面,这样也不会被访问到
    class User < ActiveRecord::Base
      attr_accessible :email, :username
    end  
  3. 在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

posted @ 2012-11-27 22:11  peterZ.D  阅读(1132)  评论(0编辑  收藏  举报