用了Rails2 以后,所有的东西都要去寻求插件帮助了, 在网上找了篇文章,好像还是挺有用的。我在本地使用act_as_authenticated 插件和Role_requirement插件还是配置成功了的
关键词: authorization(授权认证) authentication(登录认证) role based authorization Role Requirement Role Based Access Control (RBAC)
相关链接:
http://anonymouse.org/cgi-bin/anon-www.cgi/http://www.bencurtis.com/archives/2007/06/user-roles-in-rails-applications/
http://wiki.rubyonrails.com/rails/pages/Authentication+and+Security+Plugins
http://code.google.com/p/rolerequirement/
http://active-rbac.rubyforge.org/
http://wiki.rubyonrails.org/rails/pages/ActiveRBAC
http://active-rbac.rubyforge.org/
http://rubyforge.org/projects/activeacl/
http://www.billkatz.com/authorization(Authorization Plugin 详解)
http://railsforum.com/viewtopic.php?pid=2329
http://agilewebdevelopment.com/plugins/search?search=role
http://blog.wolfman.com/articles/2006/05/20/role-based-authentication-admin-page
http://www.writertopia.com/developers/authorization (Authorization Plugin 使用说明 Version 1.0 (Sept 13, 2006))
http://technoweenie.stikipad.com/plugins/show/Acts+as+Authenticated
other tips:
(较长,略)
my tips:
ActiveRBAC :
太复杂,要建立9个表!
Authorization plugin:
可配合已有登录系统使用,但需要登录系统提供一个current_user 方法(取当前已登录的用户对象)作为接口(可在ApplicationController中自定义)
每个角色需要建立一个表?from http://www.billkatz.com/authorization
语法怪异,但功能比较丰富
支持:only,:except等选项。
支持无数据库调用hardwired模式(AUTHORIZATION_MIXIN='hardwired')
支持acts_as_authorizable as well as acts_as_authorized_user:
user.has_role? 'member', Group
支持单表继承来实现多态
先在controller中设置基本权限,然后在每个action里细分权限:
class MeetingController < ActionController::Base
permit "registered", :except => :public
def public
# Anybody can access this action
end
def list
# Any "registered" user can access this action.
...
end
def add_item
# Only moderators of this meeting or a user who is an admin can add items.
permit "moderator of :meeting or admin", :meeting => Meeting.find(params[:id]) do
...
end
end
def edit
# Editing is limited to the admin of this meeting or users who have a global admin role.
@meeting = Meeting.find(params[:id])
if permit? "(admin of :meeting) or admin" # Note that no :meeting hash is provided, so @meeting is used.
# Do editing
end
end
protected
# 非公开action的保护方法
def remove_moderator
# 只允许 对象所有者 或者 管理员
permit "admin of :meeting or admin"
...# do remove process
# 删除对象后 移除 对象权限的关联
permit_set "not moderator of :meeting", :user => @removed_member
end
end
The difference between permit and permit? is redirection. permit redirects by default. permit? can be used within expressions and does not redirect by default.
User engine :
配置复杂,而功能却简单,只做到controller/action级别的限制,但有不错的view helper方法,如 link_if_authorized(controller, action),authorized?(controller, action)
RoleRequirement :
http://code.google.com/p/rolerequirement/
需先安装acts_as_authenticated 插件,(会覆盖掉unknown action)
添加两个表:roles和users_roles (通过生成器生成,名字可配置),
可建立role 或roles 两种不同关联(has_one :role 或has_many :roles),roles可以配置为enum column
权限直接在controller里设置(应该可扩展出把权限保存到数据库了,读出时覆盖controller里的默认设置),
有has_role?('admin')的辅助方法,
核心方法(controller instance method)user_authorized_for?(user_object, params = {:controller=>"user", :action=>"edit"})
view的辅助方法有:url_options_authenticate?({:controller=>"user", :action=>"edit"})
可扩展出@user.authorized_for?("/user/edit") (再尝试扩展出动态方法:@user.can_{action}_{controller}? )
似乎可扩展出object级别的限制(Business Object Permissions ):require_role "admin", :only => :update, :unless => "current_user.authorized_for_listing?(params[:id]) "
用法类似before_filter,可添加only和except来指定排除:
# * :only - Only require the role for the given actions
# * :except - Require the role for everything but
# * :if - a Proc or a string to evaluate. If it evaluates to true, the role is required.
# * :unless - The inverse of :if
class Admin::Listings < ApplicationController
require_role "contractor"
require_role "admin", :only => :destroy # don't allow contractors to destroy
end
步骤:
1.分别安装acts_as_authenticated rolerequirement
# rolerequirement的用法在README,在线的wiki没用
2.用acts_as_authenticated的generator生成user model和user controller:
#script/generate authenticated UserModelName UserControllerName
script/generate authenticated user users
(rolerequirement需要一个current_user方法做接口,如果上面生成的UserModelName不是"user",如是"person",则需要在ApplicationController里alias一个同名方法,如 alias :current_user :current_person)
# UsersController 会添加4个action: index login signup logout
#2.2 执行rake db:migrate
3.用rolerequirement的generator生成role model(留意生成完后有提示,会修改user model及ApplicationController的代码 http://code.google.com/p/rolerequirement/wiki/WhatTheGeneratorsDo):
#script/generate roles RoleModelName UserModelName
script/generate roles role user
#3.2 执行rake db:migrate
4.添加权限限制到controller中
class RolesController < ApplicationController
scaffold :role
require_role "admin"
end
5.在console里添加一个role到user
user = User.find(:first)
role = Role.find_or_create_by_name "admin"
user.roles << role unless user.roles.any?{ |r| r.name == role.name }
# 默认在User model里的has_role?方法总是返回true,如果user里有'admin' role
Active Acl:
基于 phpgacl的设计;使用polymorphic(因此需要安装has_many_polymorphs 插件) 做关联(一般都是用habtm)。封装了网状查询,只用一条SQL就能得到所有的权限数据;调用方法: current_user.has_permission?(User::LOGIN) and object level (3D, like admin.has_permission?(Forum::ADMIN, :on => team_forum)) ,设置太复杂
ACL System:
http://agilewebdevelopment.com/plugins/acl_system
可配合已有的登录系统使用,需要current_user 方法作为接口(若要改变则要hack源码),需要一个role model,且有个title属性(若要改变则要hack源码),并在user中设置habtm联系,代码也很简单。(评分挺高 Rating: 4/5 (42 votes))
没有user.has_role?('admin')这样的辅助方法
不支持直接判断controller和action,如 user.can_access?(controller, action)
需添加两个表:roles和roles_users(注意表名),权限直接在controller里设置,主要是access_control,但还要显式的与before_filter :login_required配合使用,比较麻烦:
class PostController < ApplicationController
before_filter :login_required, :except => [:list, :index]
access_control [:new, :create, :update, :edit] => '(admin | user | moderator)',
:delete => 'admin & (!moderator & !blacklist)'
end
class PostController < ApplicationController
before_filter :login_required, :except => [:list, :index]
access_control :DEFAULT => '!guest' ,
[:new, :create, :update, :edit] => '(admin | user | moderator)',
:delete => 'admin & (!moderator & !blacklist)'
end
在view中用法:
<% restrict_to "(admin | moderator) & !blacklist" do %>
<%= link_to "Admin & Moderator only link", :action =>'foo' %>
<% end %>
或
<% if permit? "(admin | moderator) & !blacklist" %>
you can ...
<% else %>
you can't ...
<% end %>
access_control :
使用较麻烦,用法类似linux的权限控制(rwx),让人迷糊,部分功能未完成:
class AdminController < ApplicationController
authorize "admin:rw"
authorize "admin:x", :only => :special_action
def index
...
end
def special_action
...
end
end
最后选择了RoleRequirement,并扩展实现了:
@user.can_{action}_{controller}?
如:
@user.can_edit_post?
下一步:model security,如:
@user.can_edit_post?(@post)