您的位置:首页 > 其它

Winform权限开发的争论-来自于伍老师

2013-09-27 15:59 246 查看
今天在伍老师的博客看到了这篇文章,对于菜鸟的我来说,的确受益匪浅!特别是在下面的一场论战中,的确综合了各家的想法!值得借鉴!下面我把伍老师的文章以及评论贴上来!

Winform开发框架之权限管理系统

在前一篇随笔《Winform开发框架之字典数据管理》中介绍过我Winform开发框架的总体情况,其中最重要的思路就是把常用的模块封装成控件进行重复使用,一则可以避免重复开发,提高开发效率;二则可以使用成熟的控件及技术,使得用户体验更好,更加专业。在前面介绍过的Winfrom开发框架总体思路如下所示。



在Winform框架中,其中权限管理系统、字典管理系统,都是可以做成独立的程序来使用,而且应该可以在程序中引用来查询或者获取相关的字典数据,如找某个键值的字典列表作为下拉列表,而且由于实际项目中,有的是SqlServer、有的是Access数据库的或者其他数据库,所以支持多数据库是最好的选择。

本篇主要介绍经过优化完善的权限管理系统, 其既独立又具整合性的权限管理系统,既相互独立,有相互整合,方便重用,又不需重新开发,非常方便、更提高效率。 由于权限系统精简而又能满足日常绝大多数的需要,不会复杂的难于管理,而且也是基于角色的授权访问机制(RBAC),最重要是非常适合软件的整合使用。

权限管理系统作为一个独立的模块,其主要由登陆界面、权限管理主界面(管理用户、角色、机构、功能,以及控制角色的权限等操作功能,部分界面如下所示。





给用户分配权限,首先是给相应角色授权,角色授权功能如下所示,可以编辑角色使用的功能,也可以管理该角色包含的用户,从而实现间接实现给用户分配权限的功能(这也是基于业界通用的基于角色的访问控制(RBAC)的控制法则)。



经过优化后的权限管理系统,界面及业务逻辑封装到一个类库中,我们开发的业务管理系统中集成就很简单了,主要的项目工程界面如下所示:



我编写了一个测试工程,用来模拟业务系统中调用权限管理模块的例子,界面如下所示:



相关的代码很简单,这也是利用权限管理系统后简化很多代码的根本所在:

private void Form1_Load(object sender, EventArgs e)

{

//获取所有权限管理系统的用户,并在下拉列表中展示

List<UserInfo> userList = BLLFactory<User>.Instance.GetAll();

this.txtLogin.Items.Clear();

foreach (UserInfo info in userList)

{

this.txtLogin.Items.Add(info.Name);

}

}

private void btnSecurity_Click(object sender, EventArgs e)

{

//独立启动权限管理系统,只需一行代码即可

WHC.Security.UI.Portal.StartLogin();

}

当然,如果要判断用户的登录及角色等,可以通过下面代码来实现。

//判断用户是否登录成功

string identity = BLLFactory<User>.Instance.VerifyUser(this.txtLogin.Text, this.txtPassword.Text, Guid.NewGuid().ToString());
if (!string.IsNullOrEmpty(identity))

{

//进一步判断用户角色

if (BLLFactory<User>.Instance.UserInRole(this.txtLogin.Text, "管理员"))

{

MessageUtil.ShowTips(string.Format("用户【{0}】身份验证正确", this.txtLogin.Text));

}

else

{

MessageUtil.ShowWarning("该用户没有管理员权限");

return;

}

}

else

{

MessageUtil.ShowWarning("用户名或密码错误");

return;

}

权限控制的精髓就是,用户登录后,通过把用户拥有的权限获取出来,放到一个功能列表中,然后在每一个窗体中,根据用户的功能列表,显示或者屏蔽对应的功能即可,获取功能列表代码如下所示:

UserInfo info = userBLL.GetUserByName(loginName);

#region 获取用户的功能列表

Function functionBLL = new Function();

List<FunctionInfo> list = functionBLL.GetFunctionsByUser(info.ID, "WareMis");

if (list != null && list.Count > 0)

{

foreach (FunctionInfo functionInfo in list)

{

if (!Portal.gc.FunctionDict.ContainsKey(functionInfo.ControlID))

{

Portal.gc.FunctionDict.Add(functionInfo.ControlID, functionInfo);

}

}

}

#endregion

判断的时候,放在一个函数,判断用户访问的功能是否在列表中即可,代码如下所示

/// <summary>

/// 看用户是否具有某个功能

/// </summary>

/// <param name="controlID"></param>

/// <returns></returns>

public bool HasFunction(string controlID)

{

bool result = false;

if (FunctionDict.ContainsKey(controlID))

{

result = true;

}

return result;

}

那么控制用户显示的界面代码如下所示:

#region KTV包间管理

if (Portal.gc.HasFunction("KTV"))

{

OutlookBarBand myBasicBand = new OutlookBarBand("KTV包间管理");

myBasicBand.SmallImageList = this.imageList;

myBasicBand.LargeImageList = this.imageList;

if (Portal.gc.HasFunction("KTV/View"))

{

myBasicBand.Items.Add(new OutlookBarItem("KTV包间状态视图", 0));

}

if (Portal.gc.HasFunction("KTV/Setting"))

{

myBasicBand.Items.Add(new OutlookBarItem("KTV包间设置", 1));

}

if (Portal.gc.HasFunction("KTV/Goods"))

{

myBasicBand.Items.Add(new OutlookBarItem("KTV商品设置", 3));

}

if (Portal.gc.HasFunction("KTV/Waiter"))

{

myBasicBand.Items.Add(new OutlookBarItem("KTV服务生管理", 4));

}

if (Portal.gc.HasFunction("KTV/BookIn"))

{

myBasicBand.Items.Add(new OutlookBarItem("KTV预订管理", 5));

}

if (Portal.gc.HasFunction("KTV/OtherIncome"))

{

myBasicBand.Items.Add(new OutlookBarItem("KTV其他款项登记", 6));

}

myBasicBand.Background = SystemColors.AppWorkspace;

myBasicBand.TextColor = Color.White;

outlookBar1.Bands.Add(myBasicBand);

}

#endregion

判断菜单或者功能按钮,也只需要判断某功能点是否在已有集合中即可,如下所示:

/// <summary>

/// 根据权限屏蔽功能

/// </summary>

private void InitAuthorizedUI()

{

this.tool_Report.Enabled = Portal.gc.HasFunction("Report");

this.tool_Dict.Enabled= Portal.gc.HasFunction("Dictionary");

this.tool_ItemDetail.Enabled = Portal.gc.HasFunction("ItemDetail");

this.tool_Purchase.Enabled = Portal.gc.HasFunction("Purchase");

this.tool_StockSearch.Enabled = Portal.gc.HasFunction("StockSearch");

this.tool_TakeOut.Enabled = Portal.gc.HasFunction("TakeOut");

this.menu_WareHouse.Enabled = Portal.gc.HasFunction("WareHouse");

this.menu_Dictionary.Enabled = Portal.gc.HasFunction("Dictionary");

this.menu_run_systemLog.Enabled = Portal.gc.HasFunction("LoginLog");

this.menu_Parameters.Enabled = Portal.gc.HasFunction("Parameters");

this.menu_MonthlyStatistic.Enabled = Portal.gc.HasFunction("MonthlyStatistic");

this.menu_AnnualStatistic.Enabled = Portal.gc.HasFunction("AnnualStatistic");

this.menu_ClearAll.Enabled = Portal.gc.HasFunction("ClearAllData");

this.menu_ImportItemDetail.Enabled = Portal.gc.HasFunction("ImportItemDetail");

}

至此,权限管理模块介绍已经完毕,下面给出一个调用例子Demo程序给大家参考学习,下载地址如下:

http://files.cnblogs.com/wuhuacong/SecurityDemo.rar

前一篇文件的字典组件模块调用例子Demo程序下载地址也一并提供下载,下载地址如下:

http://files.cnblogs.com/wuhuacong/DictionaryDemo.rar


主要研究技术:代码生成工具、Visio二次开发、送水管理软件等共享软件开发

专注于Winform开发框架、WCF开发框架的研究及应用。

转载请注明出处:


撰写人:伍华聪 http://www.iqidi.com

标签:
共享软件开发交流,
Winform开发框架
绿色通道:好文要顶关注我收藏该文与我联系





伍华聪

关注 - 46

粉丝 - 1887

荣誉:推荐博客
+加关注

23
3
(请您对文章做出评价)

«
上一篇:Winform开发框架之字典数据管理

»
下一篇:Winform开发框架之终极应用

posted on 2011-05-08 22:27
伍华聪 阅读(19295) 评论(46)

编辑
收藏

评论

#1楼

哈哈,貌似沙发,伍哥的文章要支持。
支持(0)反对(0)
2011-05-08 22:35 |
ecmascript

#2楼

不错 支持
支持(0)反对(0)
2011-05-08 22:52 |
山人不山

#3楼

非产不错,界面也很漂亮,强烈支持一下,不得不顶一下。

支持(0)反对(0)
2011-05-08 22:57 |
C#.NET通用权限管理系统组件

#4楼

权限管理功能设计的相当烂, 欠缺灵活性, 更改一些系统功能或按钮名字等的时候还要调整权限控制部分的代码. 为何不用反射使权限控制与UI代码完全分离.
支持(0)反对(0)
2011-05-08 23:03 |
wyouflf

#5楼

@C#.NET通用权限管理系统组件

界面漂亮??? 非常不错???
支持(0)反对(0)
2011-05-08 23:17 |
wyouflf

#6楼

支持一下
支持(0)反对(0)
2011-05-08 23:44 |
huyong

#7楼

密码是?
支持(0)反对(0)
2011-05-09 08:12 |
aito

#8楼

这种开源精神比什么都重要!
支持(0)反对(0)
2011-05-09 08:21 |
IT鸟

#9楼

权限设置的确有点问题,不太灵活,写了太多的if分支,修改权限的时候需要修改代码。
支持(0)反对(0)
2011-05-09 09:28 |
深蓝医生

#10楼[楼主]

@深蓝医生

权限一般是通过界面实现控制的,这里是也主要是这种实现方式,不过如果要在业务上实现控制,也可以通过本系统来实现的,因为权限控制的理念是根据控制ID来标识的。
支持(0)反对(0)
2011-05-09 09:45 |
伍华聪

#11楼[楼主]

@IT鸟

谢谢支持
支持(0)反对(0)
2011-05-09 09:46 |
伍华聪

#12楼[楼主]

@aito

admin 空密码
支持(0)反对(0)
2011-05-09 09:46 |
伍华聪

#13楼[楼主]

@C#.NET通用权限管理系统组件

呵呵,谢谢支持
支持(0)反对(0)
2011-05-09 09:46 |
伍华聪

#14楼[楼主]

@wyouflf

IT人,用成果说话,不是用贬低别人的东西来提高自己的身价

我10多款共享软件产品及众多大型项目应用的经验,难道不值得大家的参考?
支持(0)反对(0)
2011-05-09 09:48 |
伍华聪

#15楼

关注
支持(0)反对(0)
2011-05-09 09:58 |
czq blog

#16楼

顶一下!
支持(0)反对(0)
2011-05-09 10:08 |
Jack Fan

#17楼

不错,值得借鉴的,顶起
支持(0)反对(0)
2011-05-09 10:13 |
kakajay008

#18楼

上评论头条了,祝贺一下。

支持(0)反对(0)
2011-05-09 10:42 |
C#.NET通用权限管理系统组件

#19楼

博客园总有这么一些人,打击别人的开源精神!你可以善意的批评指正就够了吧,何必装的跟大牛似的,你是怪才么?
支持(0)反对(0)
2011-05-09 10:46 |
invoker707

#20楼

哈哈,有些人顶不住了??
支持(0)反对(0)
2011-05-09 11:28 |
阿超-

#21楼

LZ, it's kind of u
支持(0)反对(0)
2011-05-09 11:29 |
段少卿

#22楼[楼主]

好东西大家分享,有好的意见,集思广益,共同促进
支持(0)反对(0)
2011-05-09 12:46 |
伍华聪

#23楼[楼主]

@C#.NET通用权限管理系统组件

有你们的一份功劳,才有大家的关注,非常感谢
支持(0)反对(0)
2011-05-09 12:47 |
伍华聪

#24楼

不错,支持
支持(0)反对(0)
2011-05-09 13:51 |
风也无奈

#25楼

@invoker707

这个。。。并不开源把?老兄在哪看到的开源??
支持(0)反对(0)
2011-05-09 13:59 |
str.chan

#26楼

感谢博主分享

我发表下自己的一些观点:这种做法非常灵活,可以说是一个“通用权限组件”,不过在项目的开发过程中权限开发和业务UI、逻辑耦合度较高,修改起来比较繁琐,可以在一些公共的点上通过技术手段切入权限的控制,比如如果是Asp.Net的BS架构,比如在页面基类的AfterCreateControl,递归遍历控件树,根据权限设置以及控件的元数据绑定关系,对页面实行权限实现,如果是Winform的,可以再Form基类的AfterCreateControl之后做控制,这样业务开发人员就可以和权限开发解耦了,我做我们的产品的权限,目前就是这么做的,依托系统元数据,可以对权限做到很精细的控制,比如一个按钮,一个文本框,一个链接等等。
支持(1)反对(0)
2011-05-09 14:05 |
汽水儿

#27楼

关注
支持(0)反对(0)
2011-05-09 14:17 |
Eric·liu

#28楼

@伍华聪

引用
伍华聪:

@wyouflf

IT人,用成果说话,不是用贬低别人的东西来提高自己的身价

我10多款共享软件产品及众多大型项目应用的经验,难道不值得大家的参考?

给你的建议, 用反射解耦合!!!

可以用反射获取窗体内的(私有)控件(注意所有空间的父类型是Component,不是Control),然后动态修改控件的权限.

有经验不一定就写的好!!!

支持(0)反对(0)
2011-05-09 14:30 |
wyouflf

#29楼[楼主]

@wyouflf

如果可以,贴出的代码来说明,如果好的话,大家应该会觉得收益
支持(0)反对(0)
2011-05-09 15:18 |
伍华聪

#30楼

引用
wyouflf:

@伍华聪

引用伍华聪:

@wyouflf

IT人,用成果说话,不是用贬低别人的东西来提高自己的身价

我10多款共享软件产品及众多大型项目应用的经验,难道不值得大家的参考?

给你的建议, 用反射解耦合!!!

可以用反射获取窗体内的(私有)控件(注意所有空间的父类型是Component,不是Control),然后动态修改控件的权限.

有经验不一定就写的好!!!


不一定要在运行期反射解耦,产品发布前提取元数据到数据库,运行期根据元数据关系和控件属性以及权限设置数据,做权限控制,也不错,我做我们产品线的权限,就这门弄,业务开发部根部无需关注权限的存在。
支持(0)反对(0)
2011-05-09 15:18 |
汽水儿

#31楼[楼主]

@汽水儿

其实我规划的时候,把控制ID定义为不会重复的标识,如身份证一样,大家约定即可。
支持(0)反对(0)
2011-05-09 15:21 |
伍华聪

#32楼

引用
汽水儿:

引用wyouflf:

@伍华聪

引用伍华聪:

@wyouflf

IT人,用成果说话,不是用贬低别人的东西来提高自己的身价

我10多款共享软件产品及众多大型项目应用的经验,难道不值得大家的参考?

给你的建议, 用反射解耦合!!!

可以用反射获取窗体内的(私有)控件(注意所有空间的父类型是Component,不是Control),然后动态修改控件的权限.

有经验不一定就写的好!!!


不一定要在运行期反射解耦,产品发布前提取元数据到数据库,运行期根据元数据关系和控件属性以及权限设置数据,做权限控制,也不错,我做我们产品线的...

呵呵 根我的做法差不多, 但是我觉得只有在运行时反射才能实现:

灵活(随时重新定义权限项目),精确的权限控制,

并且可以在运行时根据角色转化(用户切换)来动态改变权限,

还能做到权限与UI,业务逻辑的彻底分离.

这才是真正的通用权限.
支持(0)反对(0)
2011-05-09 15:36 |
wyouflf

#33楼

引用
伍华聪:

@汽水儿

其实我规划的时候,把控制ID定义为不会重复的标识,如身份证一样,大家约定即可。

恩这个方案可以。

其实在产品发布前可以将这些数据提取,用户直接可以对这些设置,比如发布前写个工具反射dll,将“页面”(Form)、“控件Name”的元数据信息作为Key发布到数据库,到时候运行期设置直接选择,设置允许拒绝就好了
支持(0)反对(0)
2011-05-09 15:40 |
汽水儿

#34楼[楼主]

我遵循简单就是美的原则,一点东西不一定要设计的适应大千世界的方方面面,简单,适用,不要过度设计。 设计考虑8-2原则基本就可以了,如强大的Ruby很多东西就是约定俗成的配置,不妨碍它是世界级的语言。
支持(0)反对(0)
2011-05-09 15:49 |
伍华聪

#35楼

引用
wyouflf:

引用汽水儿:

引用wyouflf:

@伍华聪

引用伍华聪:

@wyouflf

IT人,用成果说话,不是用贬低别人的东西来提高自己的身价

我10多款共享软件产品及众多大型项目应用的经验,难道不值得大家的参考?

给你的建议, 用反射解耦合!!!

可以用反射获取窗体内的(私有)控件(注意所有空间的父类型是Component,不是Control),然后动态修改控件的权限.

有经验不一定就写的好!!!


不一定要在运行期反射解耦,产品发布前提取元数据到数据库,运行期根据元数据关系和控件属性以及权限设置数据,做权...

你说的对,运行期反射绝对是正确的,至少得到的数据是真实存在的,但是运行前工具提取发布元数据虽然在运行期效率上会高一些,但是经常会出现dll与库中的元数据不一致的情况

不过我这边是基于标准ERP产品做的权限,元数据和dll的一致性是有保障的,包括客户化开发、补丁升级都没问题,主要原因其实还是元数据在运行期软件运行平台会有其他各个方面的用途,元数据也很全面,基本涵盖了系统的各个方面,从类型、属性、UIForm、Control、Page、WebPart、Menu、模块、到UIAction、UIView、UIModel、UIField都有,不只是权限这用,所以我就借个方便用了呵呵。
支持(0)反对(0)
2011-05-09 16:05 |
汽水儿

#36楼

@伍华聪

顶楼主,有些人说话就当放屁,既然他不尊重人,没必要跟这种人一般见识。别见小孩子一般见识。
支持(0)反对(0)
2011-05-09 18:52 |
做中国最具实力的数字化系统供应商。

#37楼[楼主]

@做中国最具实力的数字化系统供应商。

本来很多东西就是仁者见仁,智者见智,谢谢你的理解及支持。

支持(0)反对(0)
2011-05-09 21:05 |
伍华聪

#38楼

等待本博最有权威的来回复哈!~
支持(0)反对(0)
2011-05-10 13:47 |
IT鸟

#39楼

引用
wyouflf:权限管理功能设计的相当烂, 欠缺灵活性, 更改一些系统功能或按钮名字等的时候还要调整权限控制部分的代码. 为何不用反射使权限控制与UI代码完全分离.

期待这位大侠的东东~,希望不是空话,

不过楼主也只是demo而已,希望能公布源码,方便大家学习研究!
支持(0)反对(0)
2011-05-12 14:08 |
爱溜达

#40楼

@爱溜达

写博客不是我的强项, 呵呵, 最近好几个项目同时开工忙死了, 过几天闲了, 在写...

不过可以先帖上权限的核心控制部分的代码:

?
getPermissionsHandler可以使权限的获取方式与权限赋值分离, 以得到多种权限组合. Lambda, Linq, 结合一个表达是就可以搞定.
支持(1)反对(0)
2011-05-12 17:01 |
wyouflf

#41楼

不是源码的呀,没有开源。
支持(0)反对(0)
2011-08-10 22:45 |
sarbro

#42楼

一般的 winform 程序就不该把权限做在 客服端。。

如数据库操作相关和对应的权限。
支持(0)反对(0)
2011-11-14 00:06 |
原来我要飞

#43楼[楼主]

引用
原来我要飞:

一般的 winform 程序就不该把权限做在 客服端。。

如数据库操作相关和对应的权限。

这个看自己的需要把,一般是通过一个入口来进行业务管理操作即可,附带权限控制有何不可,方便使用,很多时候,也需要对账号信息管理。
支持(0)反对(0)
2011-11-14 08:53 |
伍华聪

#44楼

下了你的东西 一看全是dll 都看不到什么效果 ..........................................................................................................
支持(0)反对(0)
2011-12-02 15:36 |
Faith_Ganler_lulu

#45楼

有没有源码不?怎么通过元数据来控制
支持(0)反对(0)
2012-11-05 23:56 |
123456603

#46楼

@123456603

源码太多了,大概意思就是数据库有很多表存储元数据,涵盖了系统的各个方面,包括类型啊,UI啊,字段啊,属性啊,菜单啊,页面啊,这些都是产品发布前数据库就存在的数据,然后运行期设置权限就针对元数据设置,比如那个菜单对于用户A是否可见,哪个字段对用户是否可见,是否可以编辑?然后运行期UI、菜单、字段加载等公共控制逻辑中(类型的基类中)根据权限数据对控件啊、菜单啊等做相应的控制。
支持(0)反对(0)
2012-11-06 09:18 |
汽水儿
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐