在许多书籍和教程中,我看到人们update
在用户控制器中实现该方法,通过 params[:id] 或 session[:id] 查找用户数据。但是,我觉得可以简单地修改会话或地址栏来侵入别人的帐户并修改他/她的信息。那么如何确保用户只能更新他/她自己的信息而不是更改其他信息。
4 回答
将 User 模型与任何其他模型一样对待,并向其添加您的身份验证,并要求用户在 uddate 方法中登录(例如,某些身份验证方法的 current_user )。
if current_user
update_stuff and redirect
else
:notice => 'Not authd' and redirect
end
答案是特定于应用程序的。您需要首先“找到”记录 - 如何找到该记录的详细信息取决于应用程序。
是的,正如您所指出的,您不应该只是盲目地实例化记录并更新它。您的业务逻辑需要智能地找到相关记录,然后再将其公开以进行更新。
实际上,我已经围绕这个主题进行了相当多的应用程序构建/研究,因此我将尝试给出详细的答案。
以同样的方式,您可以在非用户、登录用户和管理员帐户之间划分应用程序或网站的部分,您可以实施检查以确保例如只有正确的用户可以更改其帐户密码。这是您可能用于此类方法的测试:
describe "as wrong user" do
let(:user) { FactoryGirl.create(:user) }
let(:wrong_user) { FactoryGirl.create(:user, email: "wrong@example.com") }
before { sign_in user, no_capybara: true }
describe "submitting a GET request to the Users#edit action" do
before { get edit_user_path(wrong_user) }
specify { expect(response.body).not_to match(full_title('Edit user')) }
specify { expect(response).to redirect_to(root_url) }
end
describe "submitting a PATCH request to the Users#update action" do
before { patch user_path(wrong_user) }
specify { expect(response).to redirect_to(root_url) }
end
end
end
如果您不熟悉测试(或不确定这具体是做什么的),我将解释:
在代码中,工厂可以选择一个选项(下面的特定行)
FactoryGirl.create(:user, email: "wrong@example.com")
这基本上创建了一个与默认电子邮件地址不同的用户。然后发生的所有事情就是测试指定错误的用户不应访问原始用户的编辑或更新操作。
下一步是添加一个 before 过滤器来检查当前用户的状态。这可能会在您的users_controller.rb
文件中。
before_action :correct_user, only: [:edit, :update]
然后其次(仍然在 users_controller.tb 文件中)创建一个私有方法来检查当前用户是否有权修改数据,否则将它们重定向回根 url(如果你喜欢你可以使用 [:notice] 说“你无权访问这部分应用程序”或类似的东西)
private
def correct_user
@user = User.find(params[:id])
redirect_to(root_url) unless current_user?(@user)
end
correct_user 过滤器使用current_user?
您在 Sessions 助手中定义的布尔方法,如下所示:
def current_user
remember_token = User.encrypt(cookies[:remember_token])
@current_user ||= User.find_by(remember_token: remember_token)
end
def current_user?(user)
user == current_user
end
当涉及到谁可以访问什么时,这并不是安全的全部教条,但我希望它为您提供问题中提到的缺失细节。
我曾经在处理需要一些私有内容的应用程序时遇到过这个问题。我所做的是使用Devise和Cancan以及出色的 Rails 实践。我使用 Devise 进行身份验证,cancan 进行授权。
在某些情况下,您可以使用 hidden_field 通过表单传递用户 ID。我建议在您的控制器创建操作中传递 user_id,并且在使用设计时您可以访问 current_user 方法,该方法只会根据当前用户会话和 id 创建模型。
使用 cancan 保护用户信息。例如,如果我只能向用户展示这样的照片,而 user2 没有看到这些照片。
@photos = current_user.photos #only grabs current users photos
使用 cancan,我可以通过执行以下操作来阻止用户手动输入 users/2/edit 之类的 url
能力.rb
can :manage, Photo, :user_id => user.id
控制器.rb
load_and_authorize_resource :photo
def index
authorize! :index, @photo
end