权限控制[1] CanCan + Rolify + Devise

来源:互联网 发布:网络营销策划公司 编辑:程序博客网 时间:2024/05/22 14:24

用Gem进行安装

Reference:

  • Devise + CanCanCan + rolify

  • Devise api

说明

  • 使用devise、cancan和rolify组件建立用户权限模型的说明。
    devise:负责用户注册、登录、退出、找回密码等操作。 devise_github

  • cancan:负责角色建立、对角色授权、在页面中根据授权是否显示元素,以及模型中超出授权时抛出异常。 cancan

  • rolify:负责将用户与角色关联。rolify_github
    在Gemfile中添加如下信息

1. 安装devise, rolify, cancan

[Gemfile]gem 'devise' gem "rolify" gem 'cancan' 

然后在命令行中,用 $bundle install 进行安装。

2. Devise - install

$ rails generate devise:install

并按照提示,进行相关配置

esxi23v113@esxi23v113:~/Aptana Studio Workspace/blog$ rails generate devise:installRunning via Spring preloader in process 15821      create  config/initializers/devise.rb
create config/locales/devise.en.yml===============================================================================Some setup you must do manually if you haven't yet: 1. Ensure you have defined default url options in your environments files. Here is an example of default_url_options appropriate for a development environment in config/environments/development.rb: config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } In production, :host should be set to the actual host of your application. 2. Ensure you have defined root_url to *something* in your config/routes.rb. For example: root to: "home#index" 3. Ensure you have flash messages in app/views/layouts/application.html.erb. For example: <p class="notice"> rails g devise:views===============================================================================

3.Devise - generate user

$ rails generate devise User

4.CanCan - generate ability

esxi23v113@esxi23v113:~/Aptana Studio Workspace/blog$ rails g cancan:abilityRunning via Spring preloader in process 15759      create  app/models/ability.rb

5.Rolify - generate role

esxi23v113@esxi23v113:~/Aptana Studio Workspace/blog$ rails g rolify Role UserRunning via Spring preloader in process 16236      invoke  active_record      create    app/models/role.rb      invoke    test_unit      create      test/models/role_test.rb      create      test/fixtures/roles.yml      insert    app/models/role.rb      create    db/migrate/20170719024020_rolify_create_roles.rb      insert  app/models/user.rb
create config/initializers/rolify.rb===============================================================================An initializer file has been created here: config/initializers/rolify.rb, you can change rolify settings to match your needs. Defaults values are commented out.A Role class has been created in app/models (with the name you gave as argument otherwise the default is role.rb), you can add your own business logic inside.Inside your User class (or the name you gave as argument otherwise the default is user.rb), rolify method has been inserted to provide rolify methods.

6.Run db:migrate

esxi23v113@esxi23v113:~/Aptana Studio Workspace/blog$ rake db:migrate== 20170719023958 CreateUsers: migrating ======================================-- create_table(:users)   -> 0.0380s== 20170719023958 CreateUsers: migrated (0.0382s) =============================== 20170719024020 RolifyCreateRoles: migrating ================================-- create_table(:roles, {})   -> 0.0046s-- create_table(:users_roles, {:id=>false})   -> 0.0129s-- add_index(:roles, :name)   -> 0.0199s-- add_index(:roles, [:name, :resource_type, :resource_id])   -> 0.0046s-- add_index(:users_roles, [:user_id, :role_id])   -> 0.0041s== 20170719024020 RolifyCreateRoles: migrated (0.0467s) =======================

7.Custom Devise controller/View

Devise会帮你生成注册/登录一系列的功能,你可以定制自己想要的,只需要覆盖对应的文件or方法即可。具体参考官方文档。此处举例利用命令生成controller。

esxi23v113@esxi23v113:~/Aptana Studio Workspace/shop$ rails generate devise:controllers usersRunning via Spring preloader in process 31906      create  app/controllers/users/confirmations_controller.rb      create  app/controllers/users/passwords_controller.rb      create  app/controllers/users/registrations_controller.rb      create  app/controllers/users/sessions_controller.rb      create  app/controllers/users/unlocks_controller.rb
create app/controllers/users/omniauth_callbacks_controller.rb===============================================================================Some setup you must do manually if you haven't yet: Ensure you have overridden routes for generated controllers in your routes.rb. For example: Rails.application.routes.draw do devise_for :users, controllers: { sessions: 'users/sessions' } end===============================================================================

8.Select devise function module.

Devise 功能模块:

  1. Encryptable:除了内置的Bcrypt(默认),增加支持认证机制
  2. Lockable:锁定一定数量的失败尝试登录。通过电子邮件或之后才能解锁
  3. validatable:有效性:提供的电子邮件及密码鉴定。它是可选的,可定制的,所以你可以定义自己的代码。
  4. Timeoutable:在一特定时期(expires sessions)没有活动。
  5. Trackable(跟踪):追踪 登录的次数、时间戳记签字和IP地址。
  6. Rememberable(记忆):管理产生和清除表示来自用户保存的cookie的标记(token)
  7. Registerable(注册):处理用户注册过程,也可以让他们编辑和摧毁他们的帐户。
  8. recoverable(重设)重置用户密码并且发送重置指令。
  9. Confirmable 注册登录认证
  10. Omniauthable: adds Omniauth (github.com/intridea/omniauth) support;
  11. Database Authenticatable:登录时加密密码并在数据库中验证用户真实性。 (可以通过POST请求或HTTP基本认证)
  12. Token Authenticatable: 基于token的用户登录(also known as “single access token”)。token可以通过查询字符串或HTTP基本身份认证。

查看User.rb

你会看到device添加的模块,选择你需要的即可。

class User 

9.Use sign_in / sign_out

本功能只针对本系统,本系统自己做了登录验证,验证通过后,我们可以直接用sign_in(@user)方法把当前的user添加到session中,之后我们就可以用current_user查看当前登陆的用户。

具体可参考官方API:Method: Devise::Controllers::SignInOut#sign_in

# sign_in(resource_or_scope, *args) ⇒ Object

Sign in a user that already was authenticated. This helper is useful for logging users in after sign up. All options given to sign_in is passed forward to the set_user method in warden.

Examples:

sign_in :user, @user                      # sign_in(scope, resource)sign_in @user                             # sign_in(resource)sign_in @user, event: :authentication     # sign_in(resource, options)sign_in @user, store: false               # sign_in(resource, options)

10.Access Control (use rolify)

add_role :admin # 用来添加角色

has_role? :admin #用来判断是否有这个角色

def create    admin = Admin.new(admin_params)    if admin.save      admin.add_role params[:role]      respond_to do |format|        format.html        format.js      end    else      render 'new'    end  end

11.Set access in ability.rb

  • :manage: 是指這個 controller 內所有的 action
  • :read : 指 :index 和 :show
  • :update: 指 :edit 和 :update
  • :destroy: 指 :destroy
  • :create: 指 :new 和 :crate
  • :all 是指所有 object (resource)
  • 其他非RESTful的method (如:search)也可以列上去,但是要逐条列出来
  • 组合 : alias_action
     
    alias_action :update, :destroy, :to => :modify
    can :modify, Comment
class Ability  include CanCan::Ability  def initialize(user)    # Define abilities for the passed in user here. For example:    #    #   user ||= User.new # guest user (not logged in)    #   if user.admin?    #     can :manage, :all    #   else    #     can :read, :all    #   end    #    # The first argument to `can` is the action you are giving the user    # permission to do.    # If you pass :manage it will apply to every action. Other common actions    # here are :read, :create, :update and :destroy.    #    # The second argument is the resource the user can perform the action on.    # If you pass :all it will apply to every resource. Otherwise pass a Ruby    # class of the resource.    #    # The third argument is an optional hash of conditions to further filter the    # objects.    # For example, here the user can only update published articles.    #    #   can :update, Article, :published => true    #    # See the wiki for details:    # https://github.com/CanCanCommunity/cancancan/wiki/Defining-Abilities    user ||= User.new    if user.has_role? :admin      can :manage, :all    elsif user.has_role? :Manager      can :read, Production      can :update, Production     else      can :read, Production    end  endend

12.Access control in controller

Reference: github: authorizing-controller-actions

load_and_authorize_resource method in your controller to load the resource into an instance variable and authorize it automatically for every action in that controller

class ProductsController 

13.Access control in view

<table>  <tbody>    <% @productions.each do |production| %>      <tr>        <td><%= production.name %></td>        <td><%= production.price %></td>        <td><%= production.amount %></td>        <% if can? :read,Production%>        <td><%= link_to 'Show', production %></td>        <% end %>        <% if can? :update,Production%>        <td><%= link_to 'Edit', edit_production_path(production) %></td>        <% end %>        <% if can? :destroy,Production%>        <td><%= link_to 'Destroy', production, method: :delete, data: { confirm: 'Are you sure?' } %></td>        <% end%>      </tr>    <% end %>  </tbody></table><% if can? :create,Production%><%= link_to 'New Production', new_production_path %><% end %>
原创粉丝点击