cancancan 如何设置模型实例,以及如何检查它?

use*_*745 2 ruby-on-rails cancan cancancan ruby-on-rails-6

我注意到用户可以访问他们不应该访问的操作。

我在 Rails 控制台中用类似的东西进行了调试

user = User.first 
physician = Physician.first 
ability = Ability.new(user)
ability.can?(:send_message, physician)
# => false
Run Code Online (Sandbox Code Playgroud)

上面说用户无法访问该医生的 send_message 操作,这是所需的行为,但我知道他们可以在应用程序中!

认为这缩小了 cancancan 由于某种原因加载错误模型实例的问题的原因。cancan 文档中也暗示了这一点:

注意:这假设模型实例已正确加载。

但问题是我不确定如何从这里诊断问题,因为控制台说它应该可以工作。我不知道如何查看cancancan设置的模型实例,也不知道还能尝试什么。

有任何想法吗?

更新

我确实设法通过authorize! :send_message, physician在控制器中使用来解决这个问题,由于我只是偶然发现了这种行为,我认为弄清楚为什么加载了错误的模型实例更为重要(特别是这样我可以看看这是否是其他地方也发生过)。

我弄清楚了为什么会发生这种情况(但我仍然不知道如何诊断它)

我认为发生这种情况是因为我有很多自定义操作,有些有@physician = Physician.find(current_user.physician.id)(即他们是当前用户),而其他则更像是@physician = Physician.find_by_id(physician_params[:id]). 我不确定cancan如何设置实例模型,但我知道它不是通灵的,所以它不知道是否将其设置为当前用户的医生实例,或者传入的医生id的医生实例。

剩下什么?

cancancan 如何为自定义方法设置模型实例(我认为它会尝试一些方法,如果不起作用,则尝试其他方法,等等)?

有帮助的小注释:

  • load_and_authorize_resource 确实尝试加载模型实例以进行非 RESTful 操作
  • 文档中的一些有用信息
  • 可能和我的经历有关系:

当我返回鼻涕虫时,它打破了这种行为,我可以编辑所有神奇宝贝。

use*_*745 5

在这里留下我的笔记,以防对其他人有帮助。

TL;DR,cancancan 做出了很多微妙的假设,而你从一开始就不会知道这些假设。我通过仔细阅读 cancancan自述文件代码定义能力文档中的注释发现了其中的许多内容。

所以这里...

康康康舞如何运作

  • 如果您调用authorize!控制器操作本身,cancancan 将在每个控制器操作中查找实例变量。
  • 如果您只是load_and_authorize_resource在控制器的开头添加,则会做两件事
    1. 加载cancancan认为应该加载的实例变量,并且
    2. 检查该模型实例的授权
  • 请注意,对于自定义操作,load_and_authorize_resource仍会尝试加载模型实例,但它如何知道要加载什么?它猜测,对我来说,我不喜欢这一点,所以要注意这一点。
    • 对我来说,我更喜欢分两个单独的步骤完成自己的工作load_and_authorize_resource,因此我确切地知道发生了什么。
      1. 确保@article是通过每个控制器操作的before操作生成的(或@articles用于索引操作)
      2. 只需在控制器顶部有一行在设置模型实例的 before 操作 load_and_authorize_resource 之后
        • 请注意,唯一的区别是现在开发人员负责加载正确的模型实例,而 cancancan 不会尝试猜测它。我更喜欢这种方法,因为只需要犯一个错误就会意外地允许不应该授予的访问权限。
  • 还要记住,load_and_authorize_resource应该始终在设置模型实例变量的任何之前操作之后

随机笔记也可能有帮助

  • 实例变量的名称取决于操作。如果我们有一个文章控制器,那么:

    • 对于索引操作,授权查找 @article s
    • 对于所有其他操作,请授权查找@article
      • 然后它检查是否允许用户访问该资源。
  • load_and_authorize_resource检查模型实例是否已设置,如果没有,则设置 1。因此,如果您有一个创建 @article/@articles 的 before 操作,则load_and_authorize_resource不会为您执行此操作(即它不会覆盖它),但如果您没有设置,cancan 将尝试设置一个。查看源码中的注释:

如果实例变量已设置,则不会加载资源。这使得通过某些操作的 before_action 可以轻松地覆盖行为。

  • 能力规则将覆盖之前的规则。(参见此处的示例)
  • 最后一件事,永远不要current_user在ability.rb中使用,它会默默地出错(!!),所以一定要使用user:)