`
hideto
  • 浏览: 2652350 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

每天一剂Rails良药之Role-Based Authorization

    博客分类:
  • Ruby
阅读更多
我们的系统往往并不只是靠登录这么简单来控制权限,今天我们来看看基于角色的授权
假设我们的系统已经建立了昨天的users表

1,migration
class AddRolesAndRightsTables < ActiveRecord::Migration
  def self.up
    create_table :users_roles, :id => false do |t|
      t.column :user_id, :integer
      t.column :role_id, :integer
    end

    create_table :roles, :do |t|
      t.column :name, :string
    end

    create_table :roles_rights, :id => false do |t|
      t.column :role_id, :integer
      t.column :right_id, :integer
    end

    create_table :rights do |t|
      t.column :name, :string
      t.column :controller, :string
      t.column :action, :string
    end
  end

  def self.down
    drop_table :users_roles
    drop_table :roles
    drop_table :rights
    drop_table :rights_roles
  end
end


2,model
class User < ActiveRecord::Base
  has_and_belongs_to_many :roles
end

class Role < ActiveRecord::Base
  has_and_belongs_to_many :users
  has_and_belongs_to_many :rights
end

class Right < ActiveRecord::Base
  has_and_belongs_to_many :roles
end


3,application.rb
class ApplicationController < ActionController::Base
  layout 'standard'
  before_filter :check_authentication,
                :check_authorization,
                :except => [:signin_form, :signin]
  def check_authentication
    unless session[:user]
      session[:intended_action] = action_name
      redirect_to :controller => :admin, :action => signin_form
      return false
    end
  end

  def check_authorization
    user = User.find(session[:user])
    unless user.roles.detect{|role|
        role.rights.detect{|right|
          right.action == action_name && right.controller == controller_name
        }
      }
      flash[:notice] = "You are not authorized to view the page you requested"
      request.env["HTTP_REFERER"] ? (redirect_to :back) : (redirect_to home_url)
      return false
    end
  end
end
end


4,layout
<% if flash[:notice] %>
  <div class="errors">
    <% flash[:notice] %>
  </div>
<% end %>


如果我们的某一个controller或者action不想要check_authentication和check_authorization这两个filter,我们可以skip掉:
class HomeController < ApplicationController
  skip_before_filter :check_authentication, :check_authorization
  def index
    render :text => "A page that doesn't require a signin or any rights"
  end
end

但这只能精确到controller和action级别的权限控制
如果我们想控制对models实例的访问权限,可以参考Bruce Perens的ModelSecurity
分享到:
评论
1 楼 javafansmagic 2011-06-30  
Good~ 

相关推荐

Global site tag (gtag.js) - Google Analytics