在我的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
下面是路由。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。我可以编辑其他用户的详细信息,但不能编辑他们的密码。这是怎么回事?
有很多方法可以解决这个问题。我会试着解释一些。
我认为你的问题的关键是你混淆了MassAssignmentSecurity
的角色。您已经为admin
角色定义了Whitelist
,为default
角色定义了Blacklist
。错误提示您试图为default
角色分配Blacklist
上的内容。
既然你定义了不同的角色,我假设你可能想要这样修复它:
更改admin 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质量确定