Ruby on Rails: 使用devise+cancan+rolify创建完整的权限管理系

devise、cancan和rolify这三个组件结合,能够创建完整而强大的用户权限模型。html

  • devise介绍,负责用户注册、登陆、退出、找回密码等操做。细节参考devise on github
  • cancan介绍, 负责角色创建、对角色受权、在页面中根据受权是否显示元素,以及模型中超出受权时抛出异常。细节参考rolify on github
  • rolify介绍,负责将用户与角色关联。细节参考rolify on github

下面就简单介绍下这三者结合使用的方法,比较浅,深层次的你们本身去看文档挖掘,这里仅仅介绍最基本的使用。git

运行环境

这里我用的是ruby 1.9.3-p484       rails   3.2.16github

新建一个项目

rails new demo --skip-bundle   #跳过bundleruby

在Gemfile里面添加以下Gem包session

?
1
2
3
4
# add a perfect user verify system
gem 'devise'
gem 'cancan'
gem 'rolify'

而后运行bundle installapp

 执行devise初始化

$ rails generate devise:install

这句命令会产生一个用户指南,告诉你该作的几件事请,如下是内容翻译(已经去除heroku部署的那一条,增长了登陆退出选项的说明):post

1) 肯定你的环境中有一个缺省的URL,config/environments/development.rb:url

config.action_mailer.default_url_options = { :host => 'localhost:3000' }

若是在production环境, :host 必须设置成应用的真实主机名。spa

2) 肯定已经在config/routes.rb中定义了root_url(注意删除public下面的index.html), 例如:.net

root :to => "home#index"

可使用下面命令生成一个home#index的页面:

rails g controller home index

3) 在app/views/layouts/application.html.erb中增长消息提醒,例如:

<p class="notice"><%= notice %></p>  <p class="alert"><%= alert %></p> 

4) 不少时候还须要增长登陆、退出的选项:

?
1
2
3
4
5
6
7
     <% if current_user %>
       <%= link_to( '退出' , destroy_user_session_path, :method => :delete ) %> |
       <%= link_to( '修改密码' , edit_registration_path( :user )) %>
     <% else %>
       <%= link_to( '注册' , new_registration_path( :user )) %> |
       <%= link_to( '登陆' , new_session_path( :user )) %>
     <% end %><span></span>

5) 若是要定制Devise的view模型,能够再执行如下语句:

$ rails g devise:views

生成用户模型(你可使用其余名称代替User),并执行数据迁移

$ rails g devise User
$ rake db:migrate

 在Controller中增长认证过滤,便可在访问该模型页面时转向用户登陆页面(这自行没验证)

在须要认证的模型中,如HomeController,增长下面代码:

before_filter :authenticate_user!

集成cancan和rolify

cancan提供对资源的受权控制。例如,在视图中使用can?方法来决定是否显示某个页面元素。若是系统角色很是简单,那么cancan还在代码中直接指定常量就能够支持,具体操做能够参考官方文档。但要提供复杂的角色管理,最好的方案,仍是在devise基础上再集成cancan+rolify。

1. 修改Gemfile,并再次运行bundle install

gem 'cancan'
gem 'rolify'

2. 建立cancan的Ability和rolify的Role

$ rails generate cancan:ability
$ rails generate rolify Role User
$ rake db:migrate

3. 定制devise用户注册事件,能够在注册时赋予用户rolify角色,例如,下面的代码为首个用户赋予admin角色:

?
1
2
3
4
5
6
7
8
9
10
11
class ApplicationController < ActionController::Base
      def after_sign_in_path_for(resource)
        if resource.is_a?(User)
          if User.count == 1
            resource.add_role 'admin'
          end
          resource
        end
        root_path
      end
    end

4. 使用cancan能够为rolify中创建的角色分配受权资源,例如咱们为容许admin角色的用户分配针对全部控制类的”manage”资源,而其余用户分配”read”资源:

?
1
2
3
4
5
6
7
8
9
10
class Ability
      include CanCan::Ability
      def initialize(user)
        if user.has_role? :admin
          can :manage , :all
        else
          can :read , :all
        end
      end
    end

5. 以上已经实现了“用户-角色-权限”的三层权限模型,在view中就可使用了。例如,在Home#index页面中增长以下代码:

?
1
2
3
4
5
6
<% if user_signed_in? %>
         <p>The user is loged in .</p>
         <% if can? :manage , :Home %>
           <%= link_to "About" , home_about_path   %>
         <% end %>
     <% end %>

(完)