新手问题 cancan gem 使用问题

lzyfn123 · 2014年07月10日 · 最后由 billy 回复于 2014年07月11日 · 3203 次阅读

需求: 1、项目中绝大部分的 action 都要认证 2、有些 action 是没有实际的 model 的,是一些系统的工具(例如刷新 redis 等) 3、还有一些是 controller name 和 model name 不对应的

实验 check_authorization 是在 after_filter 中添加的,当捕获到异常时已经执行了 render 了,在跳转的话就有两个 render 了。

load_and_authorize_resource 和 authorize_resource 用这两个的话,在没有 model 的控制器中就的 skip,还得自己加验证 在有 model 控制器中,我就不能在 ApplicationController 添加,因为要在没有对应的控制器中修改 class 名称。

所以想问一下有没有好的办法

有,用 Pundit,很灵活的。CanCan 的假设太多了。

#1 楼 @billy 我只熟悉 Cancancan,今天看了下 http://www.elabs.se/blog/52-simple-authorization-in-ruby-on-rails-apps 还有 Readme https://github.com/elabs/pundit

觉得 Pundit 用在角色较少的系统中比较适用,比如说 user.admin?,或者 user.owner_of?(post),可能还可以定义个 user.moderator 之类的,如果考虑用要给用户细分权限,可能就比较麻烦了。

我看了本论坛以及 cancan wiki 的信息 https://ruby-china.org/topics/5938 把权限管理放在数据库中,这样可以实现动态定义权限,也可以动态给用户添加权限。这种要求可能不太适合使用 pundit。

实现动态定义权限,其中的 modify_service 是权限打包,详情可以参考这里

动态给用户添加权限

@Peter 谢谢讨论。我刚看了你引用的 ruby-china 的帖子,我觉得那个情景的“动态”还不能称之为真正的动态,因为规则很少也方便全部加载。真正的动态是像你说的这个场景。有 GUI,有数据库表,而且数据可能会非常多。还有类似的例子就是在 github 给一个用户授予 repo 的权限,数据是海量的。

我没有实际做过这个动态。但这种用 CanCan 来做实际上可能会比较麻烦。我不知道 CanCanCan 是怎么做的,但在 CanCan 里面,所有的 ability 其实会被执行并放入一个 instance 里面。如果有大量动态数据,这个 instance 的大小可以想见肯定无法接受。

Pundit 一样可以做动态,而且可以很灵活。

就拿你说的例子吧,比如 current_user 要创建一个联系人,那么此时就要查看他是否有权限做这个。权限是动态储存在数据库里面的。

# ContactsController
def create
  @contact = Contact.new(contact_params)
  authorize! @contact
  # ...
end

Pundit 这个authorize!很漂亮,不管静态动态,反正所有的判断逻辑都会封装到 policy 里面。

然后定义一个 Authority model,这个可以从你设定的 GUI 里面 CRUD

class Authority < ActiveRecord::Base
  # :user_id
  # :action
  # :subject
end

然后 Policy

class ContactPolicy
  attr_reader :user, :obj

  def initialize(user, obj)
    @user = user
    @obj = obj
  end

  def create?
    return true if Authority.find_by user_id: @user.id, action: 'create', subject: 'Contact'
    false
  end
end

这样就可以了,如果是 false 的话 Pundit 会扔出一个错误,然后在 controller 里面设定 rescue 就行了。

4 楼 已删除

cancan 可以通过 block 来返回 :对象否有:动作:资源 的权限 而这个操作你可以存在数据库来判断是否拥有这个权限 所以我觉得如果真的是特别复杂的操作而这个东西东西是存在数据库里 cancan 还是可以胜任的,并不需要把所有的权限定义一次性载入

现在做的就是动态添加权限,不过现在的量还是比较小的。我先试一下 Pundit,感谢各位的提点。

@wuwx 你说得对,我忘了 CanCan 可以用 block。

@Peter @lzyfn123 这些 gems 都可以做动态,不过我还是喜欢 Pundit, 胜在简单明确灵活。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号