`

使用Rails做一个RBAC的权限管理系统(不使用插件)

阅读更多
前几天,稍微分析了一下RBAC形式的权限管理系统的实现原理,然后我使用Rails做了一个。

先来说一下表间的关系:
users <--> roles roles <--> permissions
很简单,用户和角色是多对多关系,角色和权限也是多对多关系,那么关于权限管理这一块就一共有5张表。

具体的表结构:
还是直接看数据库定义文件吧!
ActiveRecord::Schema.define(:version => 20080708074044) do

  create_table "permissions", :force => true do |t|
    t.string   "name"
    t.string   "action"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "permissions_roles", :id => false, :force => true do |t|
    t.integer  "permission_id", :limit => 11
    t.integer  "role_id",       :limit => 11
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "posts", :force => true do |t|
    t.string   "title"
    t.text     "body"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "roles", :force => true do |t|
    t.string   "name"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "roles_users", :id => false, :force => true do |t|
    t.integer  "role_id",    :limit => 11
    t.integer  "user_id",    :limit => 11
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "users", :force => true do |t|
    t.string   "name"
    t.string   "password"
    t.string   "email"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

end


在User这个Model中有以下两个关键的方法:
#Get user's all permissions
	def permissions
		user_permissions = Array.new
		for role in self.roles
			user_permissions += role.permissions			
		end
		user_permissions.uniq!
		user_permissions
	end
	
	#Get user's allowed requests uri
	def permission_urls
		user_urls = Array.new
		user_permissions = Array.new
		for role in self.roles
			user_permissions += role.permissions			
		end
		for user_permission in user_permissions
			user_urls << user_permission.action			
		end
		user_urls
	end


现在,大致的意思,相信应该说清楚了吧,我对于用户权限的验证就是根据url,准确地说,应该是根据controller名称和action名称来验证的。

那么现在来看看此权限管理系统是如何工作的吧!

在用户登录时,我把用户的id存到session范围中,然后在需要进行权限保护的控制器中加入如下的过滤器:
比如我在后台管理对文章进行管理(Admin::PostController),代码如下:
before_filter :authorize, :only => [:index, :show, :new, :edit, :destroy]
	
	def authorize		
		unless User.find(session[:user_id]).permission_urls.include?( self.class.controller_path + "/" + self.action_name )	
				flash[:notice] = "You have not permission to do it!"
				redirect_to :controller => "admin/welcome"
		end
	end



以上是对于每次请求的权限控制,那么在页面上如何根据登录用户的权限显示相应的权限内容呢?
在后台管理的模块页面中,加入如下的判断语句即可。
<% if User.find(session[:user_id]).allowed_to?("admin/posts/index")%>
		<li id="posts_item"><%= link_to "Post Manage", admin_posts_path %></li>
	<% end %>


以上就是我做这个权限管理系统的基本思想,代码量比较少,思路也蛮请楚的,比较适合小型的项目。

不过我分析了一下这个权限管理系统,它就基于控制器和控制器方法的名称来判断的,而且应该是对使用generate scaffold形式生成的控制器能比较好地起作用。那么这就决定了它有多方面的不足。
1- 如何保护后台管理中的静态页面。
2- 使用不方便,在对permissions进行管理时,要求管理员比较对所用的程序比较熟悉,了解那些controller和action才行(我正在考虑怎么样让程序自动获取后台中的所有控制器和相关方法,并且显示它们的作用)
3- 权限重复比较多。
4- 与系统结合得感觉还是比较紧,我正在考虑如何运行ruby的特性将其变成一个插件(我的目标)

我正在考虑如何改进这些问题,从而做了一个轻量级的好用的权限管理系统。
分享到:
评论
12 楼 kkito 2008-08-01  
年初的时候我用了一个插件,感觉跟楼主这个差不多
activerbac
自己也思考了一下

至于那个控制粒度问题

你怎么控制粒度精确到对资源的操作?
如A建立的POSTS,B能看不能删,C是版主,能看有能删

我觉得也可以实现
应该除destory方法外还有一个destory_by_self方法
一般用户有destory_by_self的权限,而版主有destory权限
或者destory方法只能删除自己的文章,另一个admin_destory可以随便删
就能做到自己的能够删,不能删别人,版主都能删文章的功能
本来逻辑上就可以看成两码事
11 楼 lurena 2008-08-01  
这个基本没有实用性, 实现的权限管理要比这复杂得多.
做教科书还可以.
10 楼 rainchen 2008-08-01  
qichunren 写道
引用
你怎么控制粒度精确到对资源的操作?
如A建立的POSTS,B能看不能删,C是版主,能看有能删


不知道你说的是不是:
你是说对于某个特定的用户创建的资源的权限控制吗?我做的这个不能达到这个要求.

如果只有让B能看不能删posts,让C能看又能删posts,那可以通过我的这个控制.

不知道对于你说的针对某个特定的资源(在我我先暂且理解为table中的一条记录)是如何控制每个用户对其的权限控制,有什么好的方法没有??


我选用 RoleRequirement 这个插件,因为他支持eval一些自定义方法来进行细粒度的判断

class Admin::Listings < ApplicationController
  require_role "contractor"
  require_role "admin", :for => :destroy # don't allow contractors to destroy

  # leverage ruby to prevent contractors from updating listings they don't have access to.
  require_role "admin", :for => :update, [b]:unless => "current_user.authorized_for_listing?(params[:id]) "[/b]  ...
end
"




经过修改,扩展出这种形式的调用:
@user.can_{action}_{controller}?
@user.can_{action}_{controller}?(@target)

以便在View能做更细致的布局

详细可参考以前写的测试例子:
http://www.iteye.com/post/409317
9 楼 reeze 2008-07-31  
现在也很头疼这个问题。。要这针对某个资源进行访问控制。普通的基于权限的方式不是记恨有效。比如一个群组,可以设置访问权限,然后管理员 ,组成员,非组员的控制很不DRY,也很分散。。不知道有没有比较灵活的解决办法~
8 楼 universac 2008-07-29  
rainchen 写道
你怎么控制粒度精确到对资源的操作?
如A建立的POSTS,B能看不能删,C是版主,能看有能删


我现在头疼的也是这个,不光光基于角色,想把对资源的访问也统一控制,一直没有办法,现在都是分散在各个地方。不知道有谁有这方面的经验
7 楼 qichunren 2008-07-29  
引用
你怎么控制粒度精确到对资源的操作?
如A建立的POSTS,B能看不能删,C是版主,能看有能删


不知道你说的是不是:
你是说对于某个特定的用户创建的资源的权限控制吗?我做的这个不能达到这个要求.

如果只有让B能看不能删posts,让C能看又能删posts,那可以通过我的这个控制.

不知道对于你说的针对某个特定的资源(在我我先暂且理解为table中的一条记录)是如何控制每个用户对其的权限控制,有什么好的方法没有??
6 楼 rainchen 2008-07-17  
你怎么控制粒度精确到对资源的操作?
如A建立的POSTS,B能看不能删,C是版主,能看有能删
5 楼 phoenix520 2008-07-17  
qichunren 写道
phoenix520 写道
这个是用户角色资源的3层结构?我们现在使用的是用户角色权限资源的4层结构,但很多时候觉得多了那么一层,哪种结构更加合理一点呢?


说来听听呢!具体的是什么样子的呢?有什么优点?

例如人力资源部这个角色可以看到人力资源部的相关资源,财务部的角色可以看到财务部的相关资源,总经理工作部这个角色可以同时看到所有部门的资源,如果用3层结构,角色直接关联资源,那么关联总经理工作部资源的时候就会把人资部和财务部的资源再关联给总经部,会产生一些重复工作,当然也可以给总经部用户授予人资部和财务部的两个角色,不过这样并不是很直观,如果采用4层结构,财务部角色对应财务部权限,再对应财务部资源,总经部角色对应财务部权限加人资部权限,再对应相关资源,这样子可能会减少些赋权的工作量。
4 楼 qichunren 2008-07-16  
phoenix520 写道
这个是用户角色资源的3层结构?我们现在使用的是用户角色权限资源的4层结构,但很多时候觉得多了那么一层,哪种结构更加合理一点呢?


说来听听呢!具体的是什么样子的呢?有什么优点?
3 楼 superxielei 2008-07-16  
我现在使用的是三层的,并没有权限这一层,这个应该是不同的项目有不同的需求吧。
应该是四层的更完善一点,但应该是可以配置的。
2 楼 phoenix520 2008-07-16  
这个是用户角色资源的3层结构?我们现在使用的是用户角色权限资源的4层结构,但很多时候觉得多了那么一层,哪种结构更加合理一点呢?
1 楼 superxielei 2008-07-16  
说错了。还是删了吧!!

相关推荐

    [Rails 常用插件简介]CRUD Generator 2

    CRUD Generator 2就是这样一个工具,它是一个基于Edge Rails(Rails的开发版本)的高级生成器,旨在简化模型和控制器的CRUD操作的创建。 **1. Edge Rails与Rails稳定版的区别** Edge Rails指的是Rails的最新开发...

    Ruby on Rails插件

    Ruby on Rails插件是Rails框架的核心扩展机制,用于弥补Rails本身功能的不足,提供开发者所需的额外特性或功能。...插件的存在也是Rails社区活跃和生态系统繁荣的一个重要标志,为开发者提供了强大的工具和资源。

    ruby on rails在线考试系统

    7. Gems和插件:Rails社区提供了大量的Gems(Ruby的包管理系统),可以方便地扩展功能。例如,Devise用于用户认证,Cancancan进行权限控制,Paperclip或Carrierwave处理文件上传等。 8. 安全性:Rails内置了一些...

    rails 2.0.2 分页 需另外下载插件

    在Ruby on Rails框架中,`Rails 2.0.2`是一个较早的版本,而分页功能在那个时期并不像现在的Rails应用那样内置在框架内。为了实现分页,开发者通常需要安装并使用第三方插件,比如"will_paginate"。这个插件允许你在...

    Rails插件收集

    标题“Rails插件收集”指的是一个关于...总的来说,Rails插件收集是一个关于Rails开发中插件使用和管理的综合资源,包含了安装、使用、源码分析以及工具介绍等多个方面,对于Rails开发者来说是非常有价值的学习资料。

    关于Rails登录和验证插件http_authentication restful-authentication

    7. **版本控制(.svn)**: 这个文件可能表示插件曾使用Subversion作为版本控制系统。现代项目更倾向于使用Git。 随着Rails的发展,现在的认证解决方案更倾向于使用如Devise或Auth0等现成的服务,它们提供了更多的安全...

    Ruby-GoOnRails使用Rails生成器来生成一个Golang应用

    使用`GoOnRails`生成器,可以轻松地在Rails项目中添加一个新的Go应用: ```bash rails generate go_on_rails:app my_go_app ``` 这将在Rails项目的`lib/my_go_app`目录下创建一个新的Go应用结构。 ### 4. 集成Go ...

    使用Aptana+Rails开发Rails Web应用(中文)

    本教程将详细介绍如何使用Aptana与Rails结合,创建一个功能完备的Web应用程序。 首先,我们需要安装Aptana Studio。你可以从其官方网站下载最新版本的安装包。安装过程中,遵循提示进行,确保选择自定义安装并勾选...

    Ruby-RailsAdmin一个Rails引擎提供了一个易于使用的界面来管理您的数据

    在实际项目中,使用RailsAdmin 可以极大地提高开发效率,特别是在开发后台管理系统时。只需将RailsAdmin 引擎添加到Gemfile中,运行`bundle install`,然后根据官方文档进行简单的配置,就可以快速构建起一个功能...

    Ruby-DeclarativeAuthorization一个授权Rails插件在同一个地方使用声明式DSL用于指定授权规则

    总之,Ruby-DeclarativeAuthorization通过提供一个声明式的授权框架,帮助开发者在Rails应用中实现安全、一致且易于维护的权限管理。它简化了代码,提高了代码的可读性和可维护性,同时增强了应用程序的安全性。

    eclipse的ruby on rails开发插件RadRails

    RadRails是Eclipse平台上的一个开源插件,专为Ruby on Rails开发者提供了一个集成的工作环境。它提供了一系列便捷的功能,如代码编辑、调试、测试、数据库管理等,极大地提高了Rails项目的开发效率。通过安装...

    Rails上的API:使用Rails构建REST APIAPIs on Rails: Building REST APIs with Rails

    4. **实现认证和授权机制**:为了保证API的安全性,需要实现用户认证和权限管理功能,例如使用JWT(JSON Web Tokens)、OAuth等方式。 5. **错误处理**:定义一套统一的错误处理策略,当请求无法正确处理时能够向...

    VIM的Rails编辑插件rails.vim.zip

    rails.vim提供了常用的一些命令,可以帮助开发,例如:Rgenerate, Rake, Rfind,RTview等,很方便,也很实用。 安装方法: 拷贝 autoload/rails.vim, plugin/rails.vim, 和 doc/rails.txt 到 ~/.vim 目录. ...

    rails敏捷开发的购物车系统

    在本文中,我们将深入探讨如何使用Rails敏捷开发技术构建一个购物车系统,特别是在参考《rails敏捷开发第四版》中的示例。Rails 3.2.6是本文的基础框架,它是一个强大的Ruby Web应用程序框架,以其MVC(模型-视图-...

    Rails3 使用rake启动后台任务

    4. **Delayed Job (DJ)**: DJ 是一个流行的 Rails 插件,用于处理后台任务。它将任务放入数据库队列,然后在后台进程(如 worker)中执行。要使用 DJ,首先需要安装 gem,然后配置数据库连接,最后创建并运行 worker...

    jquery-rails, 一个 gem,用于自动使用jQuery和 Rails 3.zip

    jquery-rails, 一个 gem,用于自动使用jQuery和 Rails 3 railsjQuery 面向 Rails 如此伟大。这里 gem 提供:jQuery 1.7.2jQuery UI 1.8.18 ( 仅适用于 javascript )jQuery UJS适配器assert_select_j

    ruby on rails 常用插件下载

    Rails 默认并不完全支持多线程,因为 Ruby 的 GIL(全局解释器锁)会限制同一时刻只有一个线程在执行,但这并不意味着我们无法在 Rails 中实现多线程。通过一些特定的库和插件,我们可以绕过这个限制,例如使用 `...

    Rails的自动完成分页插件

    在这个场景中,我们关注的是Rails的自动完成、文件上传、分页以及上传进度管理相关的插件。让我们详细了解一下这些关键知识点: 1. **Rails 自动完成**: 自动完成是一种功能,允许用户在输入框中键入时提供预填...

Global site tag (gtag.js) - Google Analytics