Six —— 权限控制Ruby Gem

权限控制对于一个web站点为极其重要。例如 Git@OSC 中,应保证私有项目不被非项目成员访问,下载仓库,并且对于项目成员角色也应做对应的权限控制:报告者只能提 issue、开发者能进行 pull request,编写 wiki 等操作;在线阅读的站点,判断用户是非有阅读某一本书的权限。可以看出,相对于规模稍微大点的用户系统站点,权限控制为必须且为极其重要的一部分。
那么,提供给 Rubyist 的权限控制Gem都有哪些呢?punditSixcancan都为不错的选择。Git@OSC和开源项目gitlabhq使用的都是是 Six ,我对此相对熟悉,于是催生出了 Six 使用过程中的一点学习总结。

快速开始

要使用ruby gem毫无疑问得安装相对应的gem: gem install six 使用six十分简单,分为四步即可。

  1. 创建 abilities 对象
    abilities = Six.new
    
  2. 创建定义了 allowed 方法的类或对象 allowed 返回的是整个系统的权限规则数组,譬如在 Git@OSC 中项目访客对公有项目的权限为:read_project、read_wiki、read_issue、download_code、read_team_member、read_pull_request ... 譬如对于在线阅读的站点,有编辑图书,阅读图书的权限:
    class BookRules
       def self.allowed(author,book)
         [:read_book,:edit_book]
       end
     end
    
    看到了吧, allowed 方法中返回一个数组,元素包含了read_book,和edit_book的规则。这些规则的作用在第四步“如何使用”体现出来。
  3. 把第二步新建的对象添加到第一步新建的 obilities 对象
    abilities << BookRules
    
  4. 至此,可在业务开发过程中对应用户角色的权限判断了
    abilities.allowed?(@user,:read_book,@book) #true
    
    解释一下 Six 中的allow? 方法中的三个参数。首先查看其的源代码 def allowed?(object, actions, subject);....;end
    • object object trying to access resource(访问资源的对象,这个对象一般为用户)
    • actions action name to check for access(权限描述,比如这里的图书阅读权限)
    • subject resource(权限操作的资源,例如阅读图书权限操作的资源为图书,访问项目权限操作的资源为项)

Six在Ruby on Rails中的应用

从某种层面上看, Rails 确实驱动了 Ruby 的推广。使用 Six ,相信大部分开发者都是在Rails中应用,那么在Rails中如何使用Six呢?
有了上述的 quick start ,再结合Rails的规范,使用 Six 将不会是难题。首先在Gemfile中添加 gem "six"

  1. 在 ApplicationController 新建 abilities 对象。

    def abilities
     @abilities ||= Six.new
    end
    
  2. 可独立在model文件夹下新建一个 Abilities 类集中管理全站的权限,例如:

     #app/model/ability.rb
     class Ability
       self.def allow(user,subject)
         return not_auth_abilities(user,subject) if user.nil?
         return [] unless user.kind_of?(User)
         return [] if user.blocked?
    
         case subject.class.name
         when "Project" then project_abilities(user,subject)
         when "Issue" then issue_abilities(user,subject)
         ....
         else []
         end
       end
    
       def project_abilities(user,project)
         rules = []
         rules << project_guest_rules if project.public?
         ....
         rules.flatten
       end
    
       def project_guest_rules
         [
             :read_project,
             :read_wiki,
             .....
             :write_issue
         ]
       end
     end
    

    allowed方法最终返回一个包含各种权限的数组

  3. 在 ApplicationController 中把 Ability 类添加到 @abilities 对象
    def add_abilities
     abilities << Ability
    end
    
  4. 在controller和view中使用six做权限判断
    把six的allowed?方法封装为帮助方法:
    def can?(object,action,subject)
     abilities.allowed?(object,action,subject)
    end
    
  5. 确保步骤1,3,4在ApplicationController中被执行。
    • 步骤一中的 abilities 和步骤四种的 can? 方法应定义为帮助方法
    • 步骤三中的 add_abilities 应在 ApplicationController 加载时优先被执行。
      before_filter add_abilities
      helper_method :abilities, :can?
      

最后你可以在任意controller或view中使用帮助方法 can? 对用户进行权限判断了。
例如在view中判断用户是非有读仓库的操作:

can?(current_user, :read_project, @project)
0 条评论
您想说点什么吗?