Oh!Coder

Coding Life

CanCanCan Gem简介

| Comments

今天介绍的这个Gem名叫CanCanCan。CanCanCan是Ruby On Rails中可以对用户权限进行管理的一个gem。所有的相关定义都被放到了同一个位置(在Ability类中)。

这个repo是已死项目CanCan的延续。目的就是想延续CanCan的生命并且能够不断的向前发展。当前作者主要关注于1.x分支版本,目前先确保能够和Rails4能够兼容。将来作者会关注2.x分支,接过Ryan的棒子,继续向前延续CanCan。

简介

安装

对于Rails 3和Rails 4来说,在Gemfile中添加如下这行,然后执行bundle install命令。

1
gem 'cancancan', '~> 1.10'

开始

首先,CanCanCan假设current_user方法已经在controller中使用。所以首先需要添加认证功能(比如AuthlogicDevise)。除此之外,如果你有其他不同的需求,详见修改默认设置

1. 功能定义

Ability中定义用户权限。CanCan 1.5为Rails 3和Rails 4包含了一个创建这个类的生成器。

1
rails g cancan:ability

关于Abilities定义的更详细信息可参见文档

2. 核实功能和认证

当前用户的权限可以在view和controller中通过使用can?cannot?方法进行验证。

1
2
3
<% if can? :update, @article %>
  <%= link_to "Edit", edit_article_path(@article) %>
<% end %>

更多详细信息可参见对应文档

如果用户没有权限执行某个action,controller中的authorize!方法会在此用户执行这个action的时候触发异常。

1
2
3
4
def show
  @article = Article.find(params[:id])
  authorize! :read, @article
end

为每一个action都添加一行这样的代码是一件很枯燥的事情,因此load_and_authorize_resource方法自动对一个controller内所有action提供了认证功能。通过使用before filter对每一个加载到action中的资源变量进行认证。

1
2
3
4
5
6
7
class ArticlesController < ApplicationController
  load_and_authorize_resource

  def show
    # 此处的@article是已经加载并且通过认证的实例变量
  end
end

更多详情可参见对应文档

Strong Parameters

当使用strong_parameters方法或使用Rails 4+以上版本时,在存储记录之前需要对传进的参数进行过滤,比如在:create:updateaction执行之前。

默认情况下,如果你的controller将要响应如下方法,那么CanCan将会过滤传入:create:update方法的参数:

  1. create_paramsupdate_params(具体取决于你正在运行的action)
  2. < model_name >_params比如article_params(这是rails中对参数方法默认的命名惯例)
  3. resource_params(一个可以在每个controller中使用的通用名称的方法)

另外,load_and_authorize_resource现在可以通过使用params_method方法来指定一个自定义的方法过滤传入的参数。

可以关联一个param_method可选项,通过传入一个symbol类型的参数进行回调:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class ArticlesController < ApplicationController
  load_and_authorize_resource param_method: :my_sanitizer

  def create
    if @article.save
    # hurray
  else
    render :new
  end
end

private

def my_sanitizer
  params.require(:article).permit(:name)
end

当使用instance_eval时候需要包含正确的Ruby代码,此时可以在controller的context中使用字符串。在Railscast 371中,当使用PermittedParams类时会派上用场:

1
load_and_authorize_resource param_method: 'permitted_params.article'

最后,可用使用param_method方法把Proc对象关联起来,Proc对象会在controller被调用的时候执行,并且只传入一个参数:

1
load_and_authorize_resource param_method: Proc.new { |c| c.params.require(:article).permit(:name) }

更多详情可参见对应文档

3. 处理认证失败

如果用户认证失败,一个CanCan::AccessDenied异常将会被触发。可以在ApplicationController中捕捉并修改此行为。

1
2
3
4
5
class ApplicationController < ActionController::Base
  rescue_from CanCan::AccessDenied do |exception|
    redirect_to root_url, :alert => exception.message
  end
end

更多详情可参见对应文档

4. 锁定

如果你想确保application中的每一个action在执行前都要通过认证,那么需要在ApplicationController中添加check_authorization方法。

1
2
3
class ApplicationController < ActionController::Base
  check_authorization
end

如果在一个action中认证没有被执行,那么将会触发一个异常。如果想要跳过此步骤,需要在子类中添加skip_authorization_check方法。更多详情可参见对应文档

Wiki文档

更多更详细的wiki文档,可参见原文档

Comments