角色权限,RBAC
来源:互联网 发布:淘宝有没有梵楉伯勰湍 编辑:程序博客网 时间:2024/05/20 22:00
角色权限,RBAC
以上是一个简化版本关系图.
User:用户表,存放用户信息
Role:角色表,存放角色信息
UserInRole:用户角色映射表,存放用户和角色的对就关系,多对多,一个用户可以对应多个
角色,而不同的角色有一同的权限。
Permissions:权限表,不同的角色对应不同的权限。权限信息使用一个字段flag来表示,
好处是可以使用位运算来计算权限,缺点是用位标识的权限受理论值限制,如int理论上可以
标识31种不同的权限, 当然可以整加一个字段来弥补,ApplicationID标识不同的模块
Application:模块信息。
public enum Flag:long
{
View=1,
Edit=2,
Delete=4
}
特性[Flag]告诉编译器,当编译器看到Flag枚举时,它会充许你用|(or)操作符组合枚举值,
就像二的整数幂一样,
例如 Flag Administer=Flag.View|Flag.Edit|Flag.Delete;表示三种权限的组合。
基础知识:
位运算
枚举Flag
当编译器看到Flag枚举时,它会充许你用|(or)操作符组合枚举值,
就像二的整数幂一样,
例如 Flag Administer=Flag.View|Flag.Edit|Flag.Delete;
常用操作,检查是否存在
Flag administer=Flag.View|Flag.Edit|Flag.Delete;
public bool Check(Flag administer,Flag mask)
{
bool bReturn = false;
if ((administer & mask) == mask)
bReturn = true;
return bReturn;
}
调用 Check(administer,Flag.Edit)将返回true.
public Flag SetBit(Flag administer,Flag mask)
{
return administer |= mask;
}
administer |= mask;操作相当于 administer = administer |mask;
从枚举中减去一种状态
administer &=mask;
如 :
Flag administer=Flag.View|Flag.Edit|Flag.Delete;
如需要禁止删除权限.
administer &=Flag.Delete;
另外,标记为flag的枚举类型,可以不设置值
public enum Flag:long
{
View,
Edit,
Delete
}
如需要设置,按以下规律, View=1,Edit=2,Delete=4,Reply=8按2次方累加,为什么会这样?因为他使用二进制操作,
当你使用 View=1,Edit=2,Delete=3,Reply=4这样的值, Flag.Delete 包含的值是Flag.Delete还是View=1|Edit=2就无从检测了.
每个用户,可以属于不同的角色不同的角色分配不同的权限,计算所有解权的所有可能的权限组合,只要有充许的权限,那么该用户既获取该权限。
在CS系统中,Permissions表合用了二个字段来标识权限.
AllowMask,DenyMask 规责是Deny优先,也就是说当权限标记为Deny那么不论是否Allow一律禁止该用户进行此项操作。
另外,像论坛类的权限设计,仅仅一个ApplicationID字段是不够用的,因为每个版块都需要设置不同的权限,来控制权限的粒度,可在增加一张Permission表,ApplicationID修改为版块ID
这样,就可以针对不同的版块设置不同的权限
好了,接下的问题是怎么和.net自带的权限系统挂钩了。。
在asp.net系统中 ,HttpContext.Current.User实现了一个接口IPrincipal,IPrincipal包含了另一个接口Identity
我们在设计User类的时候继承此接口
public class User:IPrincipal
{
string username;
public string Username
{
get{return username;}
set{username=value;}
}
}
实现IPrincipal接口方法
public IIdentity Identity
{
get {
if (!string.IsNullOrEmpty(username))
_Identity = new GenericIdentity(username,"Forums");
return (IIdentity)_Identity;
}
}
public bool IsInRole(string role)
{
.....
}
怎样和asp.net挂钩呢,这里可以在登陆时做检查
if(HttpContext.Current!=null){
User u= Users.GetUser(name);
HttpContext.Current.User =u;
在使用时
User u = HttpContext.Current.User as User;
当然检查用户角色可以直接用
if(HttpContext.Current.User.Identity.IsAuthenticated&&HttpContext.Current.User.IsInRole(角色名))
另外可以直接把到当用户权限策略挂接到当前线程 ,使用以下方法
AppDomain.CurrentDomain.SetPrincipalPolicy(User);
好了,接下来,怎么check权限?
我倾向于使用Attribute
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method |AttributeTargets.Property | AttributeTargets.Delegate, Inherited =true, AllowMultiple = true)]
public class CheckPermissionAttribute : Attribute
{
int appID;
public int ApplicationID
{
get { return appID; }
set { appID = value; }
}
Permission _allMask;
public Permission AllMask
{
get { return _allMask; }
set { _allMask = value; }
}
public CheckPermissionAttribute(ApplicationID app, Permission allMask)
{
appID = app;
_allMask = allMask;
}
public CheckPermissionAttribute(Permission allMask)
{
_allMask = allMask;
}
}
AttributeUsage 第一个参数表示该属性可以应用于类,方法,属性,代理上
Inherited 检查继承的权限。
AllowMultiple 充许多次应用。
按下来,设计一个基类,继承自Page:
public class PageBase : Page
{
Flag _allMask;
/// <summary>
/// 检查类型权限
/// </summary>
public void CheckClass()
{
Type type = this.GetType();
CheckPermissionAttribute att =(CheckPermissionAttribute)CheckPermissionAttribute.GetCustomAttribute(type,typeof(CheckPermissionAttribute));
if (att != null)
{
Check(att.AllMask);
}
}
/// <summary>
/// 检查函数调用权限
/// </summary>
/// <param name="methodName">方法名</param>
public void CheckMethod(string methodName)
{
Type type = this.GetType();
string name = "*";
if (!string.IsNullOrEmpty(methodName))
name = methodName;
MemberInfo[] mis = type.FindMembers(MemberTypes.Method,BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public |BindingFlags.IgnoreCase,Type.FilterNameIgnoreCase,name);
foreach (MethodInfo m in mis)
{
CheckPermissionAttribute att =(CheckPermissionAttribute)CheckPermissionAttribute.GetCustomAttribute(m,typeof(CheckPermissionAttribute));
if (att != null)
{
Check(att.AllMask);
}
}
return;
}
public void Check(Flag permissions)
{
if (!CheckPermission(permissions))
{
string url = string.Format("MsgPage.aspx?msg={0}", HttpUtility.UrlEncode("您没有权限访问该资源"));
Response.Redirect(url);
}
}
public void Check(ApplicationID appID, Flag permissions)
{
PermissionManager pm= Spaces.PermissionManager.Instance(appType);
if (!CheckPermission(pm,permissions))
{
string url = string.Format("MsgPage.aspx?msg={0}", HttpUtility.UrlEncode("您没有权限访问该资源"));
Response.Redirect(url);
}
}
protected override void OnInit(EventArgs e)
{
CheckClass();
base.OnInit(e);
}
}
如何使用:
[CheckPermission(2, Flag.View)]
public partial class MyPage : PageBase
{
}
若没有查看权限,会自运导向错误页面。
在类上应用挺方便。
方法上应用我于一个方法比较麻烦,我还没有找到在页面class里怎么获取当前调用的类名.
可以调用 CheckMethod(方法名称);如
[CheckPermission(2, Flag.Delete)]
public partial class MyPage : PageBase
{
public void test()
{
CheckMethod("test");
.......
}
}
这还是需要重复劳动
posted on 2007-11-11 19:21 潇笑 阅读(5871) 评论(36) 编辑 收藏 网摘
评论
#1楼 2007-11-11 22:08sunrise想 [未注册用户]
建议 Permissions:权限表,加一个user的字段 回复 引用
#2楼 2007-11-11 23:11大石头
“方法上应用我于一个方法比较麻烦,我还没有找到在页面class里怎么获取当前调用的类名.”
如何获取调用者信息
http://www.nnhy.org/bbs/dispbbs.asp?boardID=4&ID=64&page=1 回复 引用 查看
#3楼 2007-11-11 23:12大石头
相信应该能完美的解决你的问题^_^ 回复 引用 查看
#4楼 [楼主]2007-11-12 00:42潇笑
1楼:
加一个user的字段 就没必要了,UserInRole有映射表了,性能不错。
Permissions存放权限的,若要加user字段,那和基本角色表都可以去掉了,并且这样
Permissions需要存放大量的内容,因为每个用户都需要N行记录来记录权限设置。
TO 大石头:
这个方法太帅了,可以完美解决我的问题.谢谢
回复 引用 查看
#5楼 2007-11-12 08:32大石头
呵呵,能帮上你的忙就好 回复 引用 查看
#6楼 2007-11-12 08:46chill [未注册用户]
用这个,不如用membership呢.这个与membership基本上差不多,功能上还要差些.我还以为怎么是什么好的解决方案呢.
建议多看一看membership.此方案没有新的创意或亮点,如果是在1.1环境中,无话说. 回复 引用
#7楼 2007-11-12 09:36sunrisex [未注册用户]
加一个user的字段
Permissions需要存放大量的内容,因为每个用户都需要N行记录来记录权限设置。?
假设我有一个用户属于某一个Role,但是只有某个功能他不能用(这个role的其他用户可以用),不知道你如何处理? 回复 引用
#8楼 2007-11-12 10:05森林鸟
用户中途权限发生变化时,怎么办呢
比如,屏蔽他评论,而又没有相应的角色 回复 引用 查看
#9楼 [楼主]2007-11-12 12:47潇笑
--假设我有一个用户属于某一个Role,但是只有某个功能他不能用(这个role的其他用户可以用),不知道你如何处理?
如果Permissions时有用户字段,那么每个模块,每种权限都需要加一个userID
2. 我倾向于把这个功能的用户角色映射删除,当然可以像cs系统一样,加一个Deny字段,角色禁用的权限, 禁止优先。
to:chill membership是需要自已写要限的, 这可以挂membership
也就是实现一个接口, 在web.config更改Membership的Provider配置,二者没有冲突.Membership并没有权限配置部分,只有角色吧,因为这和你实际做的项目相关,当然,通用的membership粒度控制并没那么细。
to:森林鸟
我倾向于把用户从角色中移除,当然可以向cs那样加一个Deny字段
回复 引用 查看
#10楼 2007-11-12 13:50Michael.li
写的不错,和我现在做的权限管理系统差不多.
关于怎么在方法上检测权限属性的,你可以查看我的开源ASP.NET通用权限管理系统(FrameWork).可以在http://framework.supesoft.com 下载 回复 引用 查看
#11楼 [楼主]2007-11-12 14:26潇笑
楼上的不错,界面不错 ,很好,很强大 这个我已经实现了
图:
http://xiaoxiao.bfor.cn/rbac.jpg
其实权限系统很难做到通用,否则microsoft早该集成了,membership 也只是做到角色这一级。因为不同系统之前权限差异很大. 回复 引用 查看
#12楼 2007-11-12 15:07小庄
“方法上应用我于一个方法比较麻烦,我还没有找到在页面class里怎么获取当前调用的类名.”
我的做法是建立一个页面名称和模块对应的表,从页面url中取出页面名称,在找到对应的模块ID,就不用在判断权限的方法中需要模块ID参数了。
在实际应用中并不是每个模块的权限都是一样的(浏览,添加,修改,删除等),我更倾向于把每个模块都有多少种权限也写入数据库,甚至这个权限对应的方法名也写入,这样就可以在方法内部check(反射方法名)就OK了。 回复 引用 查看
#13楼 2007-11-12 16:04静水≈深流
[CheckPermission(2, Flag.View)]
public partial class MyPage : PageBase
{
}
以前做毕业设计的时候也用这个方法的,不过现在不用了,每个页面里面要加这个方法,太累了,而且也不能够控制到按钮级的操作!也不能做到数据库动态配置和修改!
当这个页面加载的时候,你可以读到这个页面中的所有信息(页面名称,按钮名称等等)!通过这些信息去控制页面的访问权限!
比如这个页面MyPage.aspx加载的时候,数据库中配置该页面访问权限为12,页面中有个but_add按钮访问权限为 123,然后跟用户的权限去匹配,在去设置这个页面的可见度。 回复 引用 查看
#14楼 2007-11-12 16:06静水≈深流
@小庄
我们的做法比较类似!回复后才看到你的留言。 回复 引用 查看
#15楼 [楼主]2007-11-12 16:08潇笑
server form 并没有模块参数,在方法里可以CheckMethod(方法名);
不过我的目标是无需入动方法体内的代码。只应用属性来配置权限
大石头 的方法经测试,完全可行。。 回复 引用 查看
#16楼 2007-11-12 17:51sunriseyuen [未注册用户]
--假设我有一个用户属于某一个Role,但是只有某个功能他不能用(这个role的其他用户可以用),不知道你如何处理?
如果Permissions时有用户字段,那么每个模块,每种权限都需要加一个userID
为何要 每种权限都需要加一个userID ?
没有填User ID 就是 公用,填了userid 就是exception
2. 我倾向于把这个功能的用户角色映射删除,当然可以像cs系统一样,加一个Deny字段,角色禁用的权限, 禁止优先。
可能你没有明白我的意思
如
USER ROLE
A R1
B R1
C R1
D R1
...
ROLE FUNCTION
R1 F1
R1 F2
R1 F3
...
用户C的F3的功能不能用,其他的全部都能套用R1 的角色
回复 引用
#17楼 [楼主]2007-11-12 19:13潇笑
i see.其实那个那可以在配置一个Rx只包含F2,F2啊
当然我说了 另加deny这就是处理你这说的这种情况的
我就按你的说法解释一下
USER ROLE
A R1
B R1
C R1 +R2 //表示用户有R1,R2二种角色
D R1
ROLE PERMISSIONS
role allow deny
role:角色
allow:充许的权限
deny:禁用的权限
角色R1记录
role =R1
allow =F1|F2|F3;
deny =none;
--------------------------
角色R2记录
role =R2
allow =F1|F2|F3;
deny =F3;
用户A,B,C,D都属于角色R1,现在A,B,C,D分配了R1的角色,那么获取了F1,F2,F3功能,此时,你想把C用户的F3权限去除,那么只要在添加一个角
色R2就行了,因为这个规则中,禁止优先.
回复 引用 查看
#18楼 2007-11-12 20:13sunrise想 [未注册用户]
--引用--------------------------------------------------
潇笑: i see.其实那个那可以在配置一个Rx只包含F2,F2啊
当然我说了 另加deny这就是处理你这说的这种情况的
我就按你的说法解释一下
USER ROLE
A R1
B R1
C R1 +R2 //表示用户有R1,R2二种角色
D R1
ROLE PERMISSIONS
role allow deny
role:角色
allow:充许的权限
deny:禁用的权限
角色R1记录
role =R1
allow =F1|F2|F3;
deny =none;
--------------------------
角色R2记录
role =R2
allow =F1|F2|F3;
deny =F3;
用户A,B,C,D都属于角色R1,现在A,B,C,D分配了R1的角色,那么获取了F1,F2,F3功能,此时,你想把C用户的F3权限去除,那么只要在添加一个角
色R2就行了,因为这个规则中,禁止优先.
- 角色权限,RBAC
- RBAC角色权限模型设计
- RBAC角色权限模型设计
- RBAC角色权限模型设计
- 用户角色权限设计(rbac)
- RBAC用户角色权限设计方案
- RBAC用户角色权限设计方案
- RBAC用户角色权限设计方案
- RBAC用户角色权限设计方案
- RBAC用户角色权限设计方案
- 基于角色管理(RBAC)的权限系统
- 基于角色管理(RBAC)的权限系统
- 基于角色管理(RBAC)的权限系统
- 基于角色管理(RBAC)的权限系统
- 扩展RBAC用户角色权限设计方案
- 扩展RBAC用户角色权限设计方案
- RBAC角色权限系统的 一些概念
- 扩展RBAC用户角色权限设计方案
- SQL Html Mail
- 也许你不知道的c#基本数据类型及其默认值
- 应用程序权限设计
- Cognos使用Apache Web Server的配置方法
- 批处理文件bat 语法备忘
- 角色权限,RBAC
- Flash 嵌入的一个比较标准的方案
- 小老板的5个角色
- SPI,UART,I2C 各自特点 区别的一些理解
- 从sqlserver2000直接把数据导入到MySQL中
- 有状态的 socket 多线程服务器
- 表面的简洁
- 驱动开发入门记...
- 自定义 HTTP 处理程序中 Session失效的解决方案