权限管理工具的使用
在当今商业软件的开发中有一项功能是必不可少的 , 这就是权限工具 , 想必大家对权限这个词不会太陌生 , 应为在我们身边的很多软件上都用到了权限 , 比如说最常见的 Windows 操作系统,就使用到了权限,但是在实际的开发过程中,权限是个相当麻烦的东西。大家都在寻找一种简易的权限管理方式,这个时候我们发现了 CG . Security 这个组件,这是一个非常优秀的功能权限管理组件,它可以让我们非常简便的来控制软件的权限。
使用 CG . Security 你可以任意添加删除权限、角色和权限。可以通过大多数的权限管理方式给用户赋予角色或直接给用户赋予权限。
好了,简短介绍了 CG . Security 的功能后下面将为大家来讲解下该组件的用法。在讲解之前请首先到 http://www.codeproject.com/csharp/CGSecurity.asp 上下载该组件。
下面的讲解会分两个部分:
第一部分将讲解该类库中常见的一些方法属性的用法。第二部分通过一个小 DEMO ,给大家一个感性的认识,让大家了解在实际开发中如何使用 CG . Security 。
一、 类库的常用方法
在这个组件中用了六个类来分别实现了用户管理、权限管理和角色管理。
UserManager (用户管理类):该类提供了添加、删除和查找用户的方法。
RoleManager (角色管理类):该类提供了添加、删除和查找角色的方法。
RightManager (权限管理类):该类提供了添加、删除和修改权限的方法。
UserRightManager (用户权限管理类):该类的作用是使用户和权限关联,也提供了增、删、查的功能,使用此类,可以为某个用户直接赋予权限。
UserRoleManager (用户角色管理类):该类和上面的 UserRightManager 相似,也提供了相似的功能,所不同的是该类是把用户和角色进行关联。
RoleRightManager (角色权限管理类)该类提供了角色和权限关联的功能。
在介绍了上述六个类后,下面还要为大家介绍在实际开发中会用到的一个类。
SecurityManager.cs 类,该类提供了登陆验证( Authenticate )和获得该用户权限列表( EffectiveRights )的功能。使用该类我们可以判断用户的合法性并且能得到当前用户的权限列表。
上面介绍了权限管理组件中几个常见类的功能。让大家对权限管理组件有一个全面的了解,下面的一部分我将一步一步做出一个小 DEMO 让大家对这个组件有一个感性的认识。 OK ,偶们进入下一环节吧。
二、 做一个小 Demo 来演示如何使用这个权限工具
一、 做一个小 Demo 来演示如何使用这个权限工具
1. 我们在这个 Demo 中会实现数据权限和功能权限两种权限管理功能。首先我们要从网上下载该组件,该组件可以从 http://www.codeproject.com/csharp/CGSecurity.asp 上找到,在下载后在 bin/release 目录下找到 CG.Security.dll 文件。
2 .新建一个解决方案 CG.SecurityTest 。
3 .然后在 Form1 上添加一个 mainMenu, 然后在上面添家 4 个子项,把他们分别命名为 mlTest1, mlTest2, mlTest3, mlTest4, 然后把他们的 Visible 设置为 false 。
4 .当添加完菜单后我们还要添加一个 dataGrid 和 3 个按钮。
把 dataGrid 的 name 改为 dgView ; 3 个按钮分别命名为 btnAllUser 、 btnTest1 和 btnView
然后把 btnTest1 的 Enabled 属性设置为 false 。
5 .上面添加的是我们的主界面,下面我们还要添加一个用来输入用户名密码等信息的辅助界面,在工程上添加一个新的 Windows 窗体,然后命名为 FormValue 。当窗体新建好后在窗体上新建 textbox 、 button 一样两个。 textbox 分别命名为 txtName , txtPwd , button 分别命名为 btnOK , btnCancel 。并且把 btnOK 的 dialogresult 属性设置为 OK , btnCancel 的 dialogresult 属性设置为 Cancel 。窗体设置完后我们在代码中添加两个属性
public string UID
{
get { return txtName . Text . Trim();}
}
public string PWD
{
get { return txtPWD . Text . Trim();}
}
Ok 经过上述三个步骤之后我们的界面工作就完成了,下面我们将开始实现他们的具体功能 . 。
6 . 首先在项目种引用 CG.Security.dll 这个组件。在 FORM1 上导入 CG . Security 和 CG . Security . Principal 这两个命名空间。
using CG . Security;
using CG . Security . Principal;
:)这一步是必不可少的。
7. 在添加完引用后。我们还有一个东西要准备-配置文件,那么首先我们添加一个新的 App.Config ,然后 Copy 下列代码到 App.Config 中:
<? xml version ="1.0" encoding ="utf-8" ?>
< configuration >
< configSections >
< sectionGroup name ="CG.Security.Data">
< section name ="runtimeSetup" type ="CG.Security.Data.Configuration.DataSettingsHandler, CG.Security" />
</ sectionGroup >
</ configSections >
< CG.Security.Data >
< runtimeSetup defaultSection ="Access">
< installedAssembly >
< add
sectionName ="Access"
targetAssembly ="CG.Security"
targetNamespace ="CG.Security.Data.Access"
connectionString ="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=F:\tempfile\CGSecurityDemo\bin\Debug\security.mdb"
/>
</ installedAssembly >
</ runtimeSetup >
</ CG.Security.Data >
</ configuration >
上述的配置文件大家可以看到是连接数据库的一些信息,他使用到了 CG.Security.Data.Configuration.DataSettingsHandler 这个类来读取数据库信息,在配置文件中我们可以很清楚的看到连接字符串,该配置文件使用 Oledb 连接到指定目录下的 Access 数据库。应为我是放在 F 盘的,这里大家要根据自己数据库存放的实际位置来。当一切配置都完成了的时候,我们就开始实现具体的代码了。
8 .进入应用程序第一步肯定就是要验证当前用户的合法性啦, ok 那么我们首先从窗体的加载事件开始讲起:
首先我们要在定义一个全局的 string 数组 str 。
然后在 FormLoad 事件中添加如下的代码。
// 实例化登陆窗体
FormValue fv = new FormValue();
if (fv . ShowDialog( this ) != DialogResult . OK)
{
this . Close();
return ;
}
// 验证用户的 ID 和 Password
if ( ! SecurityManager . Authenticate(fv . UID,fv . PWD))
{
MessageBox . Show( " 用户名或密码不正确! " );
this . Close();
return ;
}
System . AppDomain . CurrentDomain . SetThreadPrincipal(
new CustomPrincipal( new CustomIdentity(fv . UID))
);
OleDbDataReader dataread = (OleDbDataReader)UserManager . FindByUserName(fv . UID);
dataread . Read();
str = SecurityManager . EffectiveRights(dataread . GetInt32( 0 ));
// 循环每个权限
foreach ( string strSingle in str)
{
switch (strSingle)
{
case "Test 1" :
miTest1 . Visible = true ;
btnTest1 . Enabled = true ;
break ;
case "Test 2" :
miTest2 . Visible = true ;
break ;
case "Test 3" :
miTest3 . Visible = true ;
break ;
case "Test 4" :
miTest4 . Visible = true ;
break ;
}
}
大家看到上述代码就是一个权限管理的典型应用,我将为大家一步一步讲解这段代码。
首先我们可以看到这样一段代码
FormValue fv = new FormValue();
if (fv . ShowDialog( this ) != DialogResult . OK)
{
this . Close();
return ;
}
该代码是首先实例化一个输入用户名密码的窗体,然后判断用户是否点击了 OK ,如果用户没有点击 OK 则退出程序。
if ( ! SecurityManager . Authenticate(fv . UID,fv . PWD))
{
MessageBox . Show( " 用户名或密码不正确! " );
this . Close();
return ;
}
这段代码就是精华之所在了, SecurityManager 类是一个验证类,在这里我们调用了它的 Authenticate 方法,该方法接受两个参数,用户名和密码。并返回一个 BOOL 值,借此我们可以判断该用户的用户名密码是否正确。
System . AppDomain . CurrentDomain . SetThreadPrincipal(
new CustomPrincipal( new CustomIdentity(fv . UID))
);
该句的意思是把某一用户绑定到线程的主对象上,在这里我们把当前登陆的用户 ID 传进去,那么在整个程序中都可以知道当前登陆的用户。
OleDbDataReader dataread = (OleDbDataReader)UserManager . FindByUserName(fv . UID);
dataread . Read();
str = SecurityManager . EffectiveRights(dataread . GetInt32( 0 ));
上面一段代码就是讲如何使用权限了。首先我们调用 UserManager.FindByUserName 方法得到一个 DataReader 对象(该方法是通过用户名来查找用户的信息),然后读取 DataReader 对象取得当前用户的 ID 。
最后调用 SecurityManager . EffectiveRights 方法列出该用户拥有的所有权限保存在一个字符串数组里面。
// 循环每个权限
foreach ( string strSingle in str)
{
switch (strSingle)
{
case "Test 1" :
miTest1 . Visible = true ;
btnTest1 . Enabled = true ;
break ;
case "Test 2" :
miTest2 . Visible = true ;
break ;
case "Test 3" :
miTest3 . Visible = true ;
break ;
case "Test 4" :
miTest4 . Visible = true ;
break ;
}
}
在这里我们刚才得到的权限数组,然后在判断当该用户是否拥有某个功能权限,例如 Test 1 权限的时候就让他使用 Test1 菜单和 btnTest1 按钮等。
这个时候大家可以编译程序,拿 admin 用户进系统和拿 user 进系统有什么不同之处呢?呵呵,大家可以看大使用 User 进去的时候菜单 Test1 和 Test4 不见了,还有就是 btnTest1 按钮变成灰色的了。
9. 上面,我们讲述了怎么使用功能权限,接下来,我将利用一个主从表的示例程序来为大家讲解如何使用数据权限,我们最后要实现的效果是拥有 Test4 权限的用户可以即看到主表又看到从表,反之则只能看到主表。
好了,首先我们在 bin/debug 目录下添加一个 orders.mdb 数据库,然后在里面分别建 2 张表 orders 和 orderlist 。
Orders 表字段如下
ordered 自动编号
orderType 文本 (订单类别)
orderTimer 日期时间 (发生时间)
orderlist 表字段如下
orderListID 自动编号
orderid 数字 (主表的 ID )
ProdName 文本 (商品名称)
Count 数字 (数量)
当大家把上面的表格式建立好了以后把 orders 和 orderlist 表的 orderid 值进行关联。
上述步骤做完了后就往数据库里面添加几条数据。
OK 数据库准备好了,我们也该看看怎么来实现了,在 btnView 的 click 事件中添加如下的代码:
OleDbConnection con = new OleDbConnection( @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=orders.mdb" );
con . Open();
OleDbDataAdapter da = new OleDbDataAdapter( "select * from orders" ,con);
DataSet ds = new DataSet();
da . Fill(ds, "<place w:st="on">Main</place>" );
dgView . DataSource = ds . Tables[ 0 ];
dgView . TableStyles . Clear();
DataGridTableStyle dts = new DataGridTableStyle();
DataGridTextBoxColumn dcstype = new DataGridTextBoxColumn();
DataGridTextBoxColumn dcsName = new DataGridTextBoxColumn();
dcstype . MappingName = "orderType" ;
dcstype . HeaderText = " 类型 " ;
dcsName . MappingName = "orderTimer" ;
dcsName . HeaderText = " 时间 " ;
dts . GridColumnStyles . Add(dcstype);
dts . GridColumnStyles . Add(dcsName);
dts . MappingName = ds . Tables[ 0 ] . TableName;
dgView . TableStyles . Add(dts);
foreach ( string stra in str)
{
// 如果当用户拥有该权限的时候可以看到从表里面的内容
if (stra == "Test 4" )
{
OleDbDataAdapter daList = new OleDbDataAdapter( "select * from orderList where orderid in(select orderid from orders)" ,con);
daList . Fill(ds, "List" );
ds . Relations . Add(ds . Tables[ 0 ] . Columns[ "orderid" ],ds . Tables[ 1 ] . Columns[ "orderid" ]);
DataGridTableStyle dtL = new DataGridTableStyle();
DataGridTextBoxColumn dclName = new DataGridTextBoxColumn();
DataGridTextBoxColumn dclCount = new DataGridTextBoxColumn();
dclName . MappingName = "prodName" ;
dclName . HeaderText = " 商品名 " ;
dclCount . MappingName = "count" ;
dclCount . HeaderText = " 数量 " ;
dtL . GridColumnStyles . Add(dclName);
dtL . GridColumnStyles . Add(dclCount);
dtL . MappingName = ds . Tables[ 1 ] . TableName;
dgView . TableStyles . Add(dtL);
break ;
}
}
上面的代码很简单,都是常用的数据库操作,我要讲解的是便利循环的地方。
foreach ( string stra in str)
{
// 如果当用户拥有该权限的时候可以看到从表里面的内容
if (stra == "Test 4" )
{
OleDbDataAdapter daList = new OleDbDataAdapter( "select * from orderList where orderid in(select orderid from orders)" ,con);
daList . Fill(ds, "List" );
ds . Relations . Add(ds . Tables[ 0 ] . Columns[ "orderid" ],ds . Tables[ 1 ] . Columns[ "orderid" ]);
……
}
<span
发表评论
评论