阻止其他登录用户访问“编辑”页面

时间:2011-05-18 20:31:11

标签: ruby-on-rails

我正在构建一个允许用户列出目标的小型网络应用。我希望用户只能编辑自己的内容。我已经有一个身份验证函数作为before_filter,它会检查以确保某人已登录,但它不会检查用户是否是该内容的创建者。我尝试创建第二个名为correct_user的before_filter,其代码如下:

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

为清楚起见,我使用的user_id是101,而我正在尝试编辑的goal_id是31.有人可以解释到底发生了什么吗?

另外,我知道你可以通过使用一个名为CanCan的宝石来解决这个问题(因为类似的问题得到了回答),但有没有办法在不使用宝石的情况下做到这一点?看起来我的简单小功能应该可以工作,但有人可以解释为什么不能这样做吗?

4 个答案:

答案 0 :(得分:2)

params是您的操作发送的所有参数(通过网址或表单字段等)的哈希值。参数的名称(如果存在于URL中)在路径文件中定义。对于你的目标控制器路线,你可能(大概)有:

goals_path: /goals/
goal_path: /goals/:id
edit_goal_path: /goals/:id/edit

因为您收到/goals/31/editparams[:id]为31,即您正在编辑的目标的ID。 correct_user中的第一行是查找id与params hash(goal_id)中的id匹配的User。所以,你应该做这样的事情:

def correct_user
  user = Goal.find(params[:id]).user if params[:id]
  redirect_to user_path(current_user) unless current_user?(user)
end

这说,找到有人想要编辑的目标(来自params [:id]),并给我与之关联的用户(你没有发布你的目标模型,我假设目标属于:用户但是你可能已经将其命名为“创建者”或“所有者”。如果用户与登录的当前用户不同,则重定向。您之前的代码试图找到与正在编辑的目标具有相同ID的用户。

答案 1 :(得分:2)

考虑以下假设:

  1. 用户模型:has_many :goals
  2. 目标模型:belongs_to :user
  3. 路线编辑目标:/goals/:id/edit
  4. 目标控制器,编辑操作已通过身份验证(因此您肯定会有current_user
  5. 您应该可以像这样访问目标:

    def edit
      @goal = current_user.goals.find(params[:id]) rescue redirect_to(user_path current_user)
    end
    

    这会将查找范围限定为属于current_user的目标,因此@goal将始终属于正确的用户。

答案 2 :(得分:1)

params hash中的参数id是指目标id,而不是用户id。因此,为什么你会看到一个问题。

你想做的事情就像是

def correct_user
   @goal = Goal.find(params[:id])
   redirect_to(user_path(current_user)) unless current_user?(@goal.user)
end

答案 3 :(得分:0)

其他人回答了你的主要问题,但我想这样说:我强烈建议使用CanCan,即使对于一个非常小的项目。它非常容易使用,它会帮助你很多,你会有很棒的清洁代码

例如,在您的情况下,您可以将此行放在ability.rb中以管理更新用户的目标

can :update, Goal, :user_id => user.id

并在您的控制器中只需在顶部执行load_and_authorize_resource。没有手动before_filters,不检查任何条件或类似的东西。

无论你需要在编辑目标时做些什么,比如在索引视图中说,在列出链接时,你只需要输入类似link_to_if(can?(:update, goal) , "edit goal", goal_path(goal) ){}

的内容