Ruby on rails 阻止其他登录用户访问';编辑';页
我正在开发一个小的web应用程序,允许用户列出他们的目标。我希望用户只能编辑自己的内容。我已经有了一个身份验证函数作为before_过滤器,它会检查是否有人登录,但不会检查用户是否是内容的创建者。我尝试创建第二个名为correct\u user的before\u过滤器,其代码如下:Ruby on rails 阻止其他登录用户访问';编辑';页,ruby-on-rails,Ruby On Rails,我正在开发一个小的web应用程序,允许用户列出他们的目标。我希望用户只能编辑自己的内容。我已经有了一个身份验证函数作为before_过滤器,它会检查是否有人登录,但不会检查用户是否是内容的创建者。我尝试创建第二个名为correct\u user的before\u过滤器,其代码如下: def correct_user @user = User.find(params[:id]) redirect_to(user_path(current_user)) unless current_user
def correct_user
@user = User.find(params[:id])
redirect_to(user_path(current_user)) unless current_user?(@user)
end
此外,这里是运行get请求编辑我自己的内容的服务器输出
Started GET "/goals/31/edit" for 127.0.0.1 at 2011-05-18 15:22:38 -0400
Processing by GoalsController#edit as HTML
Parameters: {"id"=>"31"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE ("users"."id" = 101) LIMIT 1
User Load (0.2ms) SELECT "users".* FROM "users" WHERE ("users"."id" = 31) LIMIT 1
Redirected to http://localhost:3000/users/101 Completed 302 Found in 49ms
Completed 302 Found in 49ms
为了清楚起见,我使用的用户id是101,我试图编辑的目标id是31。有人能解释一下到底发生了什么事吗
另外,我知道你可以通过使用一个名为CanCan的gem来解决这个问题(关于这个问题也回答了一个类似的问题),但是有没有一种不用gem的方法呢?看起来我的简单小函数应该可以工作,但是有人能解释一下为什么它不能工作吗?
params
是所有发送到操作的参数(通过url或表单字段等)的散列。参数的名称(如果存在于URL中)在路由文件中定义。对于您的目标控制器路线,您可能(大概)有:
因为您正在获取/goals/31/edit
,参数[:id]
是31,即您正在编辑的目标的id。correct_user
中的第一行是在params散列(goal_id)中查找id与id匹配的用户。所以说真的,你应该这样做:
def correct_user
user = Goal.find(params[:id]).user if params[:id]
redirect_to user_path(current_user) unless current_user?(user)
end
def edit
@goal = current_user.goals.find(params[:id]) rescue redirect_to(user_path current_user)
end
这就是说,找到某人想要编辑的目标(从params[:id]),并给我与其关联的用户(您没有发布您的目标模型,我假设目标属于:user,但您可能将其命名为“creator”或“owner”)。如果用户与当前登录的用户不同,则重定向。您以前的代码试图查找与正在编辑的目标具有相同id的用户。参数哈希中的参数id指的是目标id,而不是用户id。因此,您会看到问题 很可能你想做的是
def correct_user
@goal = Goal.find(params[:id])
redirect_to(user_path(current_user)) unless current_user?(@goal.user)
end
鉴于以下假设:
有许多目标
属于用户
/goals/:id/edit
当前用户
)def correct_user
user = Goal.find(params[:id]).user if params[:id]
redirect_to user_path(current_user) unless current_user?(user)
end
def edit
@goal = current_user.goals.find(params[:id]) rescue redirect_to(user_path current_user)
end
这将把查找范围扩大到属于
当前用户的目标,因此@goal
将始终属于正确的用户。其他人回答了您的主要问题,但我想说的是:我强烈建议使用CanCan,即使是非常小的项目。它非常容易使用,并且对您有很大帮助,而且您将拥有非常棒的干净代码
例如,在您的情况下,您可以将这一行放在ability.rb
中,以管理更新用户的目标
can:update,Goal,:user\u id=>user.id
在您的控制器中,只需在顶部执行一个加载和授权资源。在过滤前不需要手动操作,不需要检查任何条件或类似情况
无论你在什么地方需要输入一些关于编辑目标的信息,比如说在索引视图中,当列出链接时,你只需要输入一些类似于link\u to\u if(can?(:update,goal),“edit goal”,goal\u path(goal)){}
@goal=User.find
?那里可能有个打字错误!:)这就把事情弄清楚了,谢谢你!但是为什么在第一行末尾附加“if params[:id]”呢?不使用它的后果是什么?取决于您如何定义前过滤器。如果before筛选器在每个操作上运行,它将在收集操作(索引,新建)上引发RecordNotFound异常。如果您的before过滤器只在编辑、更新、销毁、创建之前运行,那么可能就没有必要了。基本上,如果第一行在params散列中找不到id,它就不会执行,而不是执行并抛出异常。再次感谢!