在任何系统中,权限设计是最基础的东西,本文给出一个基于角色的权限设计的循序渐进的设计方案。 
  在权限系统中,功能(权限)是最小的单位,比如起草新闻、编辑新闻、审核新闻、删除新闻等,而角色是一类功能的集合,比如新闻编辑这个角色,他可能有起草新闻、编辑新闻等功能集合,而责任编辑他可能就有更多的权限,比如除了新闻编辑的功能,还有审核新闻、删除新闻等功能,给张三赋予新闻编辑的角色(其实我更愿意说把张三加入到新闻编辑这个角色中去),张三就可以起草新闻、编辑新闻了,给李四赋予责任编辑的角色,李四就可以起草新闻、编辑新闻、审核新闻、删除新闻了。 
  我们来看看版本一的解决方案: 
  
  我们来模拟一下上面的数据: 
  用户信息表: 
| 
             UserID   | 
            
             UserName   | 
        
| 
             U1   | 
            
             张三   | 
        
| 
             U2   | 
            
             李四   | 
        
  角色表: 
| 
             RoleID   | 
            
             RoleName   | 
        
| 
             R1   | 
            
             新闻编辑   | 
        
| 
             R2   | 
            
             责任编辑   | 
        
  角色用户表: 
| 
             RoleID   | 
            
             UserID   | 
        
| 
             R1   | 
            
             U1   | 
        
| 
             R2   | 
            
             U2   | 
        
  功能表: 
| 
             FunctionID   | 
            
             FunctionName   | 
        
| 
             F1   | 
            
             起草新闻   | 
        
| 
             F2   | 
            
             编辑新闻   | 
        
| 
             F3   | 
            
             审核新闻   | 
        
| 
             F4   | 
            
             删除新闻   | 
        
  角色功能表: 
| 
             RoleID   | 
            
             FunctionID   | 
        
| 
             R1   | 
            
             F1   | 
        
| 
             R1   | 
            
             F2   | 
        
| 
             R2   | 
            
             F1   | 
        
| 
             R2   | 
            
             F2   | 
        
| 
             R2   | 
            
             F3   | 
        
| 
             R2   | 
            
             F4   | 
        
  我们来看看如何判断一个用户具有某个功能权限: 
  首先在用户张三登录的时候,获取张三的全部功能列表: 
Select FunctionID From 角色功能表 Where RoleID In (Select RoleID From 用户角色表 Where UserID=’U
  这样就可以得到张三的全部功能列表Functions,在起草新闻的页面我们就可以做如下判断: 
Functions.Contain(‘F
  如果为true就说明张三有起草新闻的权限。 
  当然对于web应用,您可以把Functions 用session保存起来,以避免每打开一个页面都去数据库中获取。 
  似乎看起来是一个不错的解决方案。 
  还是新闻系统,最初新闻系统没有分类,但是随着新闻的增加,没有分类的新闻看起来总是乱的,于是张三和李四给新闻添加了分类A、分类B,还是由张三负责起草,李四负责审核,以后又添加了更多的分类,并且也增加了人手,这个时候就有新的要求出来了:希望张三只负责分类A的起草,分类B的起草交给其他人做,李四呢也只负责分类A的审核(就相当于是一个栏目的责任编辑)。 
 
样的需求,版本一就无能为力了(当然你也可以增加几个功能:比如分类A的新闻起草和分类B的新闻起草,再把这个功能添加到相应的角色里面去,但是这个应该不是我们要得解决方案吧,不过版本二也是基于这个思想来解决的)。 
其实比新闻更好的例子是论坛板块的版主。 
下面是版本二的解决方案: 
在版本二的功能表中加入了一个ResourceType这个字段,这个字段用来表示对某个资源的分类(比如新闻),我们同样来模拟一下(新闻分类A的ResourceType为:NTA,分类B为:NTB): 
功能表: 
| 
             FunctionID   | 
            
             ResourceType   | 
            
             FunctionName   | 
        
| 
             F1   | 
            
             NTA   | 
            
             起草新闻:分类A   | 
        
| 
             F2   | 
            
             NTA   | 
            
             编辑新闻:分类A   | 
        
| 
             F3   | 
            
             NTA   | 
            
             审核新闻:分类A   | 
        
| 
             F4   | 
            
             NTA   | 
            
             删除新闻:分类A   | 
        
| 
             F1   | 
            
             NTB   | 
            
             起草新闻:分类B   | 
        
| 
             F2   | 
            
             NTB   | 
            
             编辑新闻:分类B   | 
        
| 
             F3   | 
            
             NTB   | 
            
             审核新闻:分类B   | 
        
| 
             F4   | 
            
             NTB   | 
            
             删除新闻:分类B   | 
        
然后在角色表添加相应的角色,在角色功能表中添加对应的功能。 
获取Functions的语句也相应地做变化: 
Select FunctionID  + ‘,’ + ResourceType From 角色功能表 Where RoleID In (Select RoleID From 用户角色表 Where UserID=’U
权限的判断也就变成: 
Functions.Contain(‘F1,NTA’); 
在新添加一个分类的时候,同时也在功能表中增加相应的记录(当然不是在数据库里面直接添加,由和功能相关的函数来添加)。 
使用这种解决方案可以简单地对有分类的应用(比如论坛系统)的每个分类实行不同的控制(比如VIP板块,就只能拥有VIP角色的用户才能浏览、发表等,而其他板块只要是注册用户就可以使用了)。 
在实际应用中FunctionID并不是随便的一个字符串,而是进行了编码,其编码中包含了模块ID以及能够体现出父子关系,举个例子来说:对于论坛系统,我们给它一个模块ID为”
300101:删除帖子 
300201:发帖 
300202:回帖 
300203:浏览帖子 
对于资源(比如某个板块1,板块的ID为:01),我们可以组合出如下的Functions(当然这个组合你也可以不用逗号分隔,用其他的组合方式也可以,不过不要产生歧义): 
300101,01:板块1删除帖子的功能 
                    
                
                
            
        
浙公网安备 33010602011771号