1

在我正在使用的 RoR 应用程序中,客户端需要进行一些自定义 - 基本上他要求管理员能够更改其他用户的密码,并且密码更改页面与编辑个人资料详细信息的页面不同。我已经设置了自定义操作来处理这个问题,即我自己在用户控制器中的 change_password 操作。

Users Controller Actions
def change_password
    @user = User.find(params[:id])
  end

  def update_password # I post to this
    @user = User.find(params[:id])
    if @user.update_attributes!(params[:user])
      redirect_to users_path, :notice => "User updated."
    else
      redirect_to users_path, :alert => "Unable to update user."
    end
  end

这是 routes.rb 条目

devise_for :users, :skip => [:registrations]                                          
    as :user do
      get 'users/edit' => 'devise/registrations#edit', :as => 'edit_user_registration'    
      put 'users' => 'devise/registrations#update', :as => 'user_registration'            
    end
  resources :users
...

  match "/users/:id/change_password" =>"users#change_password", :as=>:change_password_user, :via=>:get
  match "/users/:id/update_password" => "users#update_password", :as=>:update_password_user, :via=>:post

这是我的用户模型

class User < ActiveRecord::Base
  rolify
  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable,
  # :lockable, :timeoutable and :omniauthable, :registerable,
  devise :database_authenticatable, #:registerable,
         :recoverable, :rememberable, :trackable, :validatable

  # Setup accessible (or protected) attributes for your model
  attr_accessible :role_ids, :as => :admin
  attr_protected :username, :name, :email, :password, :password_confirmation, :remember_me

  validates_uniqueness_of :username
  validates_presence_of :username, :email

  validates_uniqueness_of :email
end

但是我不断收到这个质量属性分配错误

Can't mass-assign protected attributes: password, password_confirmation

奇怪的是我已将所有这些属性设置为accessible_protected。我可以编辑其他用户的详细信息,但不能编辑他们的密码。这里发生了什么?

4

1 回答 1

2

有很多方法可以解决这个问题。我将尝试解释一些。

我认为你的问题的关键是你混淆了MassAssignmentSecurity角色。您已经为角色定义了 a并Whitelistadmin角色定义了 a 。该错误表明您尝试分配角色上的某些内容。BlacklistdefaultBlacklistdefault

由于您正在定义不同的角色,我假设您可能希望以这种方式修复它:

更改您的管理员Whitelist

attr_accessible :role_ids, :password, :password_confirmation, as: :admin

然后分配为管理员:

if @user.update_attributes!(params[:user], as: :admin)

(如果您的控制器操作包括密码字段以外的字段,这可能会导致新的违规行为。)

另一种选择是坚持使用默认角色。您可以通过几种方式绕过安全性。

我不推荐的第一个选项是不将密码和密码确认作为User参数的一部分传递,并在您的视图中单独发送。然后,您可以像这样手动设置这些字段:

@user.assign_attributes(params[:user])
@user.password = params[:password]
@user.password_confirmation = params[:password_confirmation]
if @user.save!

但是,执行以下操作更容易跳过保护:

@user.assign_attributes(params[:user], without_protection: true)
if @user.save!

有关更多信息,本指南相当不错: http: //guides.rubyonrails.org/security.html#mass-assignment

我希望这会有所帮助。

于 2013-01-15T16:16:47.940 回答