权限控制对于一个web站点为极其重要。例如 Git@OSC 中,应保证私有项目不被非项目成员访问,下载仓库,并且对于项目成员角色也应做对应的权限控制:报告者只能提 issue、开发者能进行 pull request,编写 wiki 等操作;在线阅读的站点,判断用户是非有阅读某一本书的权限。可以看出,相对于规模稍微大点的用户系统站点,权限控制为必须且为极其重要的一部分。
那么,提供给 Rubyist 的权限控制Gem都有哪些呢?pundit、Six和cancan都为不错的选择。Git@OSC和开源项目gitlabhq使用的都是是 Six ,我对此相对熟悉,于是催生出了 Six 使用过程中的一点学习总结。
快速开始
要使用ruby gem毫无疑问得安装相对应的gem: gem install six
使用six十分简单,分为四步即可。
- 创建 abilities 对象
abilities = Six.new
- 创建定义了 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的规则。这些规则的作用在第四步“如何使用”体现出来。
- 把第二步新建的对象添加到第一步新建的 obilities 对象
abilities << BookRules
- 至此,可在业务开发过程中对应用户角色的权限判断了
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"
。
- 在 ApplicationController 新建 abilities 对象。
def abilities
@abilities ||= Six.new
end
- 可独立在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方法最终返回一个包含各种权限的数组
- 在 ApplicationController 中把 Ability 类添加到 @abilities 对象
def add_abilities
abilities << Ability
end
- 在controller和view中使用six做权限判断
把six的allowed?方法封装为帮助方法:
def can?(object,action,subject)
abilities.allowed?(object,action,subject)
end
- 确保步骤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)
网友评论