当前位置:  技术问答>java相关

关于用户角色权限管理的探讨

    来源: 互联网  发布时间:2015-04-29

    本文导语:  用户权限管理是我们在做应用时经常遇到的问题,但是我们是不是曾经对它做过比较深入的分析呢?不同的系统中的用户管理是不是可以抽象出一个通用的模型呢?  我们先来看一个最普通的例子:论坛。 为了便于分析,论...


用户权限管理是我们在做应用时经常遇到的问题,但是我们是不是曾经对它做过比较深入的分析呢?不同的系统中的用户管理是不是可以抽象出一个通用的模型呢? 

我们先来看一个最普通的例子:论坛。 为了便于分析,论坛的用户我们简化成三类:普通用户和版主。 

以CSDN为例,sharetop是java版的版主,所以他登录的过程是这样: 

登录(普通用户)->进入Java版(版主)->进入C++版(普通用户)->回到Java版(版主) 

从现象上分析,在切换不同页面的时候,角色发生了改变,是吧?对应上面的过程,在sharetop登录后用RID来记录他的当前角色。 那它的变化就是 

User->Sysop->User->Sysop。

于是,我们要解决的问题是:如何决定这个RID的变化? 

if( BlockID is java && my.name is sharetop ) my.RID=sysop; else my.RID=user; 

那第二个问题是:这个IF语句是如何产生出来的? 

我们在数据库中建立这样一个表role_table: 

UID RID BID 
sharetop sysop java 
sharetop user c++ 

于是,我们根据这个表的内容去生成这个判断语句,上面的代码改成: 

select RID from role_table where BID=current.BlockID and UID=my.name; my.RID= selected RID; 

我们再优化一下,其它普通用户实在没必要记录,所以上表只需记录是sysop的用户的UID和BID即可。 命名为bolck_sysop_table

UID RID BID 
sharetop sysop java 
yanchang sysop jsp 

(*)注意:我给出的表都只是逻辑结构并非真正的物理结构:),比如这两个字段可能被放在block_table中,而不是用一个独立的表来保存。下同。 

RID可以保存在session中或是用有状态会话Bean来处理,只在每个版区的入口页面加入角色变化的验证代码,后面的页面即使用session中的RID值。同样,如果加上帖主的角色,唯一的区别在于验证代码应存在于显示帖子的页面,使用RID的页面也只有显示帖子的页面了。 

在这个例子中我们看到这么一个现象:普通用户覆盖了全部的版区,在这个大集合里有一些子集,如java版版主、C++版版主等等。每个版主都是普通用户这个超类的某个子类,是具有特殊权限的普通用户。 

 
问题是不是得到了解决?看起来好象是的:) OK,那我们来看另一个复杂一些的例子吧。 

我们有一个非常简单的电子政务系统,假如只有一部分:信访室和检查室。
我们的用户只有四类:信访室主任、信访室办信人、检查室主任、检查室办案人。 

首先,我们来看一下它的权限分配(假设我是局长我修改了规则):
办信人A处理信访件xf001,那另一个办信人B就不能对xf001进行操作包括看都不行。但是信访室主任C可以看任何信访件,但是不能修改。xf001交到检查室,由D承办,他也可以看xf001的内容但不能修改,检查室主任E看不到任何xf001的内容,但E可以看xf001中的由D新增加的内容。 

是不是有点复杂了?:)那么我们上面分析的模型是不是能拿来用呢?想想,有点问题。 

本例中,信访室和检查室是两个相对独立的集合,所以我们先分开来考虑:
在信访室内部,对于xf001,A有操作权,C有观看权,B没有权限。对应表的role_xf_table如下: 

UID RID BID 
A oper xf001 
B oper xf002 

于是我们这样分配他们的权限: 

select RID from role_xf_table where (BID=current.xfNo or RID=leader) and UID=my.name; my.RID=selected RID; 
if( my.RID==oper) permit operate. 
if( my.RID==leader) permit view. 

单纯的信访室内部,这样似乎没问题了,但是上面的权限分配中提到xf001交到检查室后,由D承办,他也可以看xf001的内容。于是上面的模型肯定要修改。 

在这里,我们需要再引入一个“组”的概念。


信访室是一个组,在这个组内,我们可以用上面分析的模型对它的权限管理进行控制,同样,检查室也是一个组,组内的权限管理也可以套用我们上面的模型。但是组与组之间的权限管理呢?

D属于检查组,他却对信访室组中的xf001的内容有观看权,我们要修改上面的表,加入组GID,如下表role_group_table:

UID RID GID BID 
A oper xf xf001 
B oper xf xf002 
C leader xf   
D oper jc aj001=xf001 
E leader jc   

* aj001是另一个操作对象,它与xf001之间有关联。也正是有这个关联,我们允许操作aj001的D有权限看xf001的内容。为了简化分析,我们把aj001等同于xf001。 

我们的语句是: 

select RID,GID from role_group_table where (BID=current.blockID or RID=leader) and UID=my.name;
f( oper of xf ) permit operate. 
if( oper of jc ) permit view. 
if( leader of xf ) permit view. 

是不是有那么点道理?好,我们还可以对这个再做一下优化,比如这三个条件判断,不一定要写死在程序中,我们应该为它建立一个“RID与GID权限组合分配表”,字段为:RID、GID、Authority。 

其实,在这里的RID也是另一个组的概念:oper组与leader组。我们可以为leader赋于一个共同的权限(比如收某种级别的公文等)。 

其实这个模型还有很多要进一步讨论的地方,不过它大体上解决了问题,我们先放一放,再来看另一个模型吧。 

第三个例子是:一个广告管理系统。用户可以分为三种:系统管理员、广告管理员和广告主用户。 

系统管理员负责广告管理员的新增和删除。广告管理员只负责定向与数个广告主联系,并为他们提供广告业务。而广告主是我们的客户,每个广告主可能有几个广告。广告管理员只能看、修改自己负责的广告主的资料和此广告主交付的广告的资料。而广告主也只能看自己的广告的统计资料。 

这里的权限比较简单,我们注意到这样的语汇:只能……自己……。所以这里的权限是一棵树。 

如果我们继续沿用上面的分析,并且在这里也试着引入组的概念,如果每个广告管理员算为一个组,那么这个组里又可以分为每个广告主的一个小组?是不是这样?所以,这里的组有一种嵌套的关系,这也正是树的结构。如果不把它叫做组,这里的权限其实就是具有分级分支的关系。 

我们再回过头来看一下上面的例子,在第二个例子中,组似乎有交叉的关系?如果RID与GID都被称为组,那它们之间的确是交叉的。 再看第一个例子,比较发现,如果把广告系统看成一个论坛,广告主相当于帖主,广告管理员就是板主,那么,唯一的区别在于每个帖主只能在自己特定的版区活动,java的兄弟不能去C++玩,这样看来,其实广告系统的权限才是最简单的。 

与论坛系统对照而言,广告主也可以看作是广告管理员的一个子集,但是不是为他增加了某些权限,相反是削减了某些权限。 

好象是这么一回事。这样一来,我们也可以用论坛使用的那一套数据表结构来描述它了。把BID改为PID,分别用role_table记录广告主与广告管理员的权限和ad_table记录广告与广告主的关系: 


UID RID PID 
a oper a 
b oper b 
c adver a 
d adver a 
e adver b 
 ID OWN 
1 c 
2 c 
3 d 
4 e 
5 e 
6 e 
 

语句这样: 

select role.PID from role_table,ad_table where role_table.UID=ad_table.OWN and ad_table.ID=current.ID; 
if( selected role.PID is my.name ) permit operate. 
else forbid. 

是不是表述了这个关系? 好吧,先到这里。 

我要声明一点的是:这不是什么指南,也不是想告诉你如何如何做。只是我对这个问题的一些思考,我尽可能地把我纷繁的头绪整理出来,但是还是很乱,而且考虑得也很片面和肤浅,之所以拿出来,只是为了抛砖引玉,能引出您的真知灼见。 

所以,我期待着你的参与,就上面的例子,或是你实际工作中的例子,给我们讲述一下你的思路。 

欢迎致信yancheng@sharetop.com,我们一起讨论这个问题。 
 

|
user表
USER_ID 
其它属性

op表
USER_ID(foreign key)
BOARD_ID(foreign key)
其他属性

board表
BOARD_ID
BOARD_NAME

public class Operator {
  int board_id;
  其它属性
}

public class UserInfo {
  String user_id;
  Operator[]  ops; //记录了user是那些版的版主
  
  其他属性
}

public class UserDAO {
  public static UserInfo getUserInfo(String user_id) throws SQLException {
    从数据库中读取用户user_id的资料,返回UserInfo
  }
}

public class UserAction {
  String user_id;
  int    board_id;
  int    action_id;
}

public class csdn {
  UserCache userCache = new UserCache();
  public void login(String user_id) {
    UserInfo userIndo = getUserInfo(user_id);
    if( user_info!=null ) 把userInfo放到UserCache中
    ....
  }
  public void onAction(UserAction userAction) {
    UserInfo userInfo = getUserInfoFromCache();
    checkAction(userInfo,userAction);//对用户的操作进行权限检查
  }
}

|
权限的管理可以说在每个系统中都会遇到看了以上的大虾们的,忍不住想跟各位大虾们交流一下
在最近做的一个项目中(有关CRM)的我们对权限的管理思路如下:
我们使用了分组的形式,对于不同组有不同的权限,一个角色是属于一个组的。
在论坛中也可以用这种思路
版主是一个组OPER
interface OPER
{
   定义基本权限(抽象级)
}
基本用户组User
interface USER
{
    定义基本权限
}
注意以上都是interface因为我们对一个User组一个Oper组都不知道它们有一些什么权限(在论坛中表现为功能)也就是具体实现不管,它只定义了一个模具而已。以后其它的每一个论坛都实现这个模具,都跟这个样子差不多。
至于论坛中用户ID的来回切换
一个简单实用效的方法就是先把用户的在整个系统中的所有权限都一次性的读出来
保存为一个全局变量性的数据结构,这样不必在每次变换时都读数据库。这就是叫用内存换取速度。
以上只是个人思路,并没有具体的实现。
本人也正在做这方面的工作,写成一个通用的类库。现在这个类库差不多快完成,正在测试中!
欢迎大家来email:jiang_it@21cn.com讨论

    
 
 

您可能感兴趣的文章:

  • 深入探讨:Oracle中如何查询正锁表的用户以及释放被锁的表的方法
  • 如何能让低权限用户执行高权限用户的命令
  • 如何给用户管理员设置权限及组的权限设置
  • 添加用户后,如何分配权限给这个用户
  • root用户附权限给其他用户问题
  • 权限,怎样设置非root用户对目录的读写运行权限
  • 监听低端口,用户没权限,这个权限要怎么加?实在没分了。。
  • 求助:忘记了root用户的密码,如何给普通用户赋root权限
  • 如何编程使普通用户拥有访问/root目录的权限(即超级权限)
  • 新建一个用户,然后用ssh登陆,我能否限制该用户只能访问默认目录,其他目录都没有权限进入?
  • 在redhat7.2中只有root权限才可以直接读写声卡文件吗?怎样设置普通用户的权限使其可以直接访问声卡?
  • 公共用户的执行权 限,读权限和写权限究竟有何区别和意义?
  • 怎样让普通用户拥有超级用户的权限,是把普通用户的组设为root组吗?具体怎么做,急死了
  • 请问在redhat8.0里如何将其他用户的权限赋给其他用户?
  • 创建了一个用户,可是登陆后该用户对对应的目录没有写权限
  • 如何root和新加sis用户的权限
  • 怎么给一指定用户增加权限
  • linux如何给指定用户赋予指定文件的权限
  • 如何设定(或更改)用户创建文件时的缺省权限???
  • 我想用其他用户修改root权限的文件该如何做?
  • 如何把目录的写权限分配给用户
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • SQL SERVER 利用存储过程查看角色和用户信息的写法
  • 在tomcat 中使用jdbcrealm是否一定要在数据库中建立用户表和 角色表
  • Oracle 8x监控sysdba角色用户登陆情况
  • SQL Server中查询用户的对象权限和角色的实例代码
  • Oracle新建用户、角色,授权,建表空间的sql语句
  • oracle用户权限、角色管理详解
  • Linux常用命令介绍:更改所属用户群组或档案属性
  • 概念混乱,请专人解释:实际用户ID,有效用户ID,设置用户ID
  • Linux进程的内核栈和用户栈概念,相互关系及切换过程
  • proftp中,如何让FTP的用户是非Linux用户,只是FTP用户?
  • UIO(linux Userspace I/O子系统)用户空间设备驱动I/O技术介绍
  • windows 系统是否是多用户操作系统,如何理解“多用户操作系统”的“多用户”?
  • CentOS安装Telnet,以root用户登陆Telnet以及CentOS的各种终端解释
  • 我装的是RED HAT LINUX 8.0,我在root用户中把root用户删除了,怎办也进不了root用户
  • 我一个服务器同时接受到很多个用户的认证请求(得到用户名和密码),然后把用户名密码发给认证服务器。因为是远程认证,所
  • 我装了中软Linux3.1,启动时要求输入用户名和口令,但安装时并没有提示指定用户名,所以现在输入用户名老是错误,不能进入系统,请问该怎
  • 如何添加一个用户,让这个用户只能访问某个特定的目录,
  • 如何过滤系统用户只显示创建的用户?
  • 匿名用户登录nobody用户的作用
  • 怎样在程序中将普通用户切换成root用户
  • 创建用户组创建用户出错
  • 请教用户组和用户的问题
  • Public key用户 创建的用户不能登录
  • 利用root用户修改一般用户密码的批处理文件怎么写呢?
  • **********如何在UNIX上创建一个用户,此用户只能访问自己的目录***********
  • UNIX里每个用户是否对应一个用户目录?
  • linux ftp用户组下的用户限制指定目录


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3