【问题标题】:Issues with CanCan authorization - Author edits PostCanCan 授权问题 - 作者编辑帖子
【发布时间】:2013-08-28 03:41:40
【问题描述】:

我正在开发一个 Rails 应用程序,使用 CanCan 进行授权。该应用程序具有数据库模型 User 和 PositionGameStat。 PositionGameStat 有一个外键 user_id。 position_game_stat 的索引页面显示了用户提交的统计信息列表,每个统计信息都有一个编辑按钮。目前它很容易被注入 (... /position_game_stats/130/edit)

我希望用户只能编辑与当前用户相同的 position_game_stat 条目。

换句话说,如果有人试图注入 url .../position_game_stats/129/edit 并且他们没有输入这些统计信息,CanCan 将拒绝访问

下面是我的代码。

我的代码: app/controllers/position_game_stats_controller.rb

class PositionGameStatsController < ApplicationController  

    before_filter :authenticate_user! 
    ...   
    def edit
      authorize! :manage, @position_game_stat 
      @position_game_stat = PositionGameStat.find(params[:id])
    end 
    ... 
  end

app/models/ability.rb

class Ability
  include CanCan::Ability

  def initialize(user)
    can :show, User, :id => user.id
    can :manage, PositionGameStat do |t|
      t.user_id == user.id
    end  
  end 
end

非常感谢任何建议。

更新: 根据比利陈的建议,这段代码似乎至少更接近一些: 能力

class Ability
  include CanCan::Ability

  def initialize(user)
    can :show, User, :id => user.id
    can :manage, PositionGameStat do |t|
      t.user == current_user
    end
  end
end

控制器

class PositionGameStatsController < ApplicationController

  before_filter :authenticate_user!

...

  def edit
    authorize! :manage, PositionGameStat
    @position_game_stat = PositionGameStat.find(params[:id])
  end
...
end

这让我更加接近,因为它不会拒绝访问页面,但它仍然容易受到注入。例如 /position_game_stats/137/edit 仍然可以访问,即使它是由其他用户创建的。

有什么建议吗?

【问题讨论】:

  • 你为什么要在@position_game_stat 被赋值之前授权它?您遇到的具体问题是什么?
  • 我遇到的问题是授权阻止用户编辑 position_game_stat。我让它为“用户”工作,因此您无法将不同的用户值注入参数中,但现在我正在使用外键,并且在使用 position_game_stat 模型时遇到问题。

标签: ruby-on-rails devise authorization cancan


【解决方案1】:

在你的ability.rb中你需要指定授权规则应该如何应用:

  can :manage, PositionGameStat, PositionGameStat.find_all_by_user_id(user.id) do |position_game_stat|
    position_game_stat.new_record? or position_game_stat.user.id == user.id
  end

在您的控制器中,您可以通过以下方式应用授权:

  load_and_authorize_resource

注意:load_and_authorize_resource 实际上会做类似@position_game_stat = PositionGameStat.find(params[:id]) 的事情。如果您不希望这种行为,您可以像这样手动执行授权:

  @position_game_stat = PositionGameStat.accessible_by(current_ability).find(params[:id])

最后请参阅 CanCan 文档的这一部分了解更多详细信息:https://github.com/ryanb/cancan/wiki/Defining-Abilities-with-Blocks

【讨论】:

  • 得到错误未定义的方法“包括?”对于#<0x007fb117473180>
【解决方案2】:
can :manage, PositionGameStat do |t|
  t.user == current_user
end  

完成。

更新

好的,我看到了问题。这行错了

authorize! :manage, @position_game_stat

您仅授权此特定实例。那是错的。应该是

authorize! :manage, PositionGameStat

【讨论】:

  • 很遗憾,这对我不起作用,CanCan 仍然拒绝访问。
  • @lando2319,你准备好current_user 方法了吗?来自 Devise 或您自己的。
  • 其实我只是注意到它仍然容易被注射。例如 /position_game_stat/137/edit 是可以访问的,即使它来自不同的用户。我会继续努力的。
【解决方案3】:

最终解决方案: PositionGameStatsController.rb

    class PositionGameStatsController < ApplicationController

      before_filter :authenticate_user!

      load_and_authorize_resource

...

      def edit
        authorize! :manage, PositionGameStat
        @position_game_stat = PositionGameStat.find(params[:id])
      end
...
    end

能力.rb

class Ability
  include CanCan::Ability

  def initialize(user)
    can :show, User, :id => user.id
    can :manage, PositionGameStat do |t|
      t.user.id == user.id
    end
  end
end

感谢 Billy Chan 和 Steakchaser 的建议,这足以让我前进。 current_user 出于某种原因在 Ability.rb 中不起作用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-02
    相关资源
    最近更新 更多