如果一个系统需要很灵活的权限系统,我们一般会采用RBAC(基于角色的操作控制).我对此的理解,按照UML用例图,可以把分离出资料和操作两个元素,再加上角色.RBAC的东西就齐了.
关于RBAC的数据库设计以及代码的书写,本文不想论述,我这里只想谈一下,如何在代码的基础上,更好的使用它.
在使用时,我们要把每个UI控件的事件,如Button.Click事件和一个对资源的操作绑定起来,这样,在我们点击按钮时,通过一定的方法,我们去验证该用户(角色)是否对指定的资源有指定的操作权限,从而做出判断. 而这个一定的方法,我想到两种:
一. 通过代码直接在事件中写,如
protected void btnDelete_Click(
)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
if(!xx.HaveRight("user","delete"))
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
throw new RbacNoRightException()
}
else
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// code here
}
}
但是这种方式,个人感觉把 "user","delete"这两种东西写死在代码里面了,不是很好.以后要是有什么改动,还得重新编译程序集.
二. 通过继承重写 Button,注册 Button.Click事件,控制先执行我拉的委托函数A,在这个函数中,来判断权限.
示例代码如下:
public class RbacButton : System.Web.UI.WebControls.Button, IRbacControl
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
protected override void OnInit(EventArgs e)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this.Click += new EventHandler(RbacButton_Click);
this.Command += new CommandEventHandler(RbacButton_Command);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
base.OnInit(e);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
void RbacButton_Command(object sender, CommandEventArgs e)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
TryRight();
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
void RbacButton_Click(object sender, EventArgs e)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
TryRight();
}
.
}
TryRight就是我们用来判断权限的函数了.但这里有一个问题,我们的控件是共同的控件,不可以知道应该如何判断.但是,在共同控件中,我们可以得到Page的实例,这个应该知道如何判断权限了吧.
所以,判断权限代码如下面形式:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
共用部分#region 共用部分
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private bool isHaveRight = true; //因为如果 RbacResourceAlias 为空,则默认有权限
protected bool IsHaveRight
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (System.Web.HttpContext.Current == null)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return true;
}
if (EnableRbac)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
string rrid = this.RbacResourceAlias;
string opid = this.RbacOperationAlias;
if (rrid != "" && opid != "")
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
isHaveRight = Rbac.HaveRight(rrid,opid);
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
return isHaveRight;
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public override bool Visible
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return base.Visible && this.IsHaveRight;
}
set
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
base.Visible = value;
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private void TryRight()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (!this.IsHaveRight)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
throw new RbacControlException(this.RbacResourceAlias);
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
IRbacControl Members#region IRbacControl Members
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private bool enableRbac = true;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
[Category("RBAC"), Description("是否启用权限认证"), DefaultValue(true)]
public bool EnableRbac
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return enableRbac; }
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{ enableRbac = value; }
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private string rbacResourceAlias = string.Empty;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
[Category("RBAC"),Description("权限资源标识"),DefaultValue("")]
public string RbacResourceAlias
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return rbacResourceAlias;
}
set
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
rbacResourceAlias = value;
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private string rbacOperationAlias = string.Empty;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
[Category("RBAC"),Description("权限操作标识"),DefaultValue("")]
public string RbacOperationAlias
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return rbacOperationAlias;
}
set
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
rbacOperationAlias = value;
}
}
private IRbac rbac = null;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public IRbac Rbac
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (this.rbac == null)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
rbac = this.Page as IRbac;
}
return rbac;
}
set
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
rbac = value;
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
解决了上面的问题,稍带也把没有权限的按钮设置成不显示了,有好处吧! 下面就可以看下如何使用了.
<asp:RbacButton ID="btnSave"
RbacResourceAlias="user.card"
RbacOperationAlias="modify"
runat="server"
OnClick="OnSaveCard"
Text="修改" />
这下简单多了.修改也简单.