AppBox 是基于 FineUI 的通用权限管理框架,包括用户管理、职称管理、部门管理、角色管理、角色权限管理等模块。

AppBox v2.0中的权限实现

AppBox v2.0中权限管理中涉及三个概念:模块、用户、角色

1. 权限是定义在模块中,而模块相当于一个分组,比如用户管理就是一个模块。用户分组模块可以包含的多个页面,比如用户列表页面、新增用户页面、修改用户页面、用户详细信息查看页面、修改用户密码页面等;

2. 角色拥有对权限的控制,可以设置一个角色拥有哪些权限;

3. 一个用户可以有多个角色,用户最终的权限来自己所属角色的权限集合。

下面看一下在AppBox v2.0中设置角色权限的页面:

通过上面的描述可以看出,“模块”在整个权限设计中并不重要,仅仅相当于权限的一个分组。

为什么说AppBox v2.0中的模块是鸡肋!

“模块”的引入使得系统看起来更加复杂,比如判断一个用户对某个页面是否有浏览权限?

明显角色模块权限表的设计会比较复杂,因为每个模块的权限个数不同,可以需要特殊的结构。

在AppBox v2.0中,我们是通过JSON结构保持除浏览权限之外的所有权限。来看下数据库表X_RoleModule的初始化脚本:

SET IDENTITY_INSERT [dbo].[X_RoleModule] ON
INSERT [dbo].[X_RoleModule] ([Id], [RoleId], [ModuleName], [CanRead], [Others]) VALUES (311, 1, N'CoreUser', 1, N'{"New":true,"Edit":true,"Delete":true,"ChangePassword":true}')
INSERT [dbo].[X_RoleModule] ([Id], [RoleId], [ModuleName], [CanRead], [Others]) VALUES (312, 1, N'CoreRoleUser', 1, N'{"New":true,"Delete":true}')
INSERT [dbo].[X_RoleModule] ([Id], [RoleId], [ModuleName], [CanRead], [Others]) VALUES (313, 1, N'CoreRoleModule', 1, N'{"Edit":true}')
INSERT [dbo].[X_RoleModule] ([Id], [RoleId], [ModuleName], [CanRead], [Others]) VALUES (314, 1, N'CoreRole', 1, N'{"New":true,"Edit":true,"Delete":true}')
INSERT [dbo].[X_RoleModule] ([Id], [RoleId], [ModuleName], [CanRead], [Others]) VALUES (315, 1, N'CorePassword', 1, N'{"Edit":true}')
INSERT [dbo].[X_RoleModule] ([Id], [RoleId], [ModuleName], [CanRead], [Others]) VALUES (316, 1, N'CoreOnlineUser', 1, N'')
INSERT [dbo].[X_RoleModule] ([Id], [RoleId], [ModuleName], [CanRead], [Others]) VALUES (317, 1, N'CoreMenu', 1, N'{"New":true,"Edit":true,"Delete":true}')
INSERT [dbo].[X_RoleModule] ([Id], [RoleId], [ModuleName], [CanRead], [Others]) VALUES (318, 1, N'CoreLog', 1, N'{"Delete":true}')
INSERT [dbo].[X_RoleModule] ([Id], [RoleId], [ModuleName], [CanRead], [Others]) VALUES (319, 1, N'CoreJobTitle', 1, N'{"New":true,"Edit":true,"Delete":true}')
INSERT [dbo].[X_RoleModule] ([Id], [RoleId], [ModuleName], [CanRead], [Others]) VALUES (320, 1, N'CoreDept', 1, N'{"New":true,"Edit":true,"Delete":true}')
INSERT [dbo].[X_RoleModule] ([Id], [RoleId], [ModuleName], [CanRead], [Others]) VALUES (321, 1, N'CoreConf', 1, N'{"Edit":true}')
INSERT [dbo].[X_RoleModule] ([Id], [RoleId], [ModuleName], [CanRead], [Others]) VALUES (322, 1, N'AppFile', 1, N'')

这种复杂性不仅在数据库设计阶段,在代码编写阶段也不大好处理,需要大量的代码维护权限列表的读写操作。

下面的代码是更新角色对应的模块权限列表的后台代码:

FineUI.CheckBoxField canReadField = Grid2.FindColumn("CanRead") as FineUI.CheckBoxField;
XRoleModuleCollection roleModules = new XRoleModuleCollection();
foreach (GridRow row in Grid2.Rows)
{
int rowIndex = row.RowIndex; object[] dataKeys = Grid2.DataKeys[rowIndex];
// 当前行对应的模块名称
//int moduleId = Convert.ToInt32(dataKeys[0]);
string moduleName = dataKeys[1].ToString(); bool canRead = canReadField.GetCheckedState(rowIndex);
AspNet.CheckBoxList ddlOthers = (AspNet.CheckBoxList)Grid2.Rows[rowIndex].FindControl("ddlOthers"); JObject otherPowerObj = new JObject();
foreach (AspNet.ListItem item in ddlOthers.Items)
{
if (item.Selected)
{
otherPowerObj.Add(item.Value, true);
}
} if (canRead || otherPowerObj.Count > 0)
{
XRoleModule roleModule = new XRoleModule();
roleModule.RoleId = roleId;
roleModule.ModuleName = moduleName; roleModule.CanRead = canRead;
if (otherPowerObj.Count > 0)
{
roleModule.Others = otherPowerObj.ToString(Newtonsoft.Json.Formatting.None);
}
else
{
roleModule.Others = "";
} roleModules.Add(roleModule);
}
}
roleModules.BatchSave();

在这段代码中,我们不仅需要更新浏览权限,还需要将其他权限生成JSON字符串,并插入数据库。  

此外由于我们还要维护菜单列表,在菜单和模块的关系上用户也产生了疑问,来看下编辑菜单的页面截图。

用户需要进一步地了解如下概念:

1. 一个模块可以对应多个页面;

2. 一个页面可以是菜单项,也可以不是菜单项;

3. 需要指定一个菜单项所属的模块,以便根据权限定义生成左侧菜单项。

AppBox v3.0全新的“扁平化权限设计”! 

我不清楚这个概念之前是否有人提过,不过这是独立思考的结果,因此我就给他起了个响亮的名字 - “扁平化的权限设计”。

之所以是扁平化,是因为我们舍弃了“模块”的页面,所以的权限(在其他系统中可能称之为功能点)都可以单独定义,而每个页面只需要在这个很大的权限集合中选中自己需要的权限子集(通常,在实践中这个过程是相反的:也即是每个页面定义自己需要的权限集合,所有页面的权限集合形成了整个站点的权限集合)。

扁平化的权限设计示意图:

数据库设计简单,自然代码就简单了。前面足足 40 多行的保存权限的代码,现在不用 20 行就实现了:

// 当前角色新的权限列表
List<int> newPowerIDs = new List<int>();
for (int i = 0; i < Grid2.Rows.Count; i++)
{
AspNet.CheckBoxList ddlPowers = (AspNet.CheckBoxList)Grid2.Rows[i].FindControl("ddlPowers");
foreach (AspNet.ListItem item in ddlPowers.Items)
{
if (item.Selected)
{
newPowerIDs.Add(Convert.ToInt32(item.Value));
}
}
} Role role = DB.Roles.Include(r => r.Powers).Where(r => r.ID == roleId).FirstOrDefault();
ReplaceEntities<Power>(role.Powers, newPowerIDs.ToArray()); DB.SaveChanges();

为了避免权限集合过于分散,我们还为每个权限定义了 GroupName (分组属性),从而在前台展示时更美观,更简洁。

权限表的模型类:

public class Power
{
[Key]
public int ID { get; set; } [Required, StringLength(50)]
public string Name { get; set; } [StringLength(50)]
public string GroupName { get; set; } [StringLength(200)]
public string Title { get; set; } [StringLength(500)]
public string Remark { get; set; } public virtual ICollection<Role> Roles { get; set; } }

保存角色权限的页面截图:

  

虽然界面和之前的差不多,但内部实现已经简化了很多。

菜单项编辑时,只需要指定菜单项对应的浏览权限即可(如果不指定浏览权限,则默认这个菜单项不参与权限控制),如下图所示。

下载或捐赠AppBox

1. AppBox v2.0 是免费软件,免费提供下载:http://fineui.com/bbs/forum.php?mod=viewthread&tid=3788

2. AppBox v3.0 是捐赠软件,你可以通过捐赠作者来获取AppBox v3.0的全部源代码(http://fineui.com/donate/)。

返回《AppBox升级进行时》目录

喜欢这篇文章,请帮忙点击页面右下角的【推荐】按钮。

后记

感谢各位网友的支持,本文再次荣登【10天推荐排行榜】第一名,上一次登上第一名是:#CSDN刷票门# 有没有人在恶意刷票?CSDN请告诉我!用24小时监控数据说话!

此活动已结束,不会再单独发送PDF文件。

《AppBox升级进行时》前 7 篇文章已经全部在博客公开,请大家直接在我的博客上浏览。后面的文章还没开始写。

AppBox升级进行时 - 扁平化的权限设计的更多相关文章

  1. AppBox升级进行时 - 拥抱Entity Framework的Code First开发模式

    AppBox 是基于 FineUI 的通用权限管理框架,包括用户管理.职称管理.部门管理.角色管理.角色权限管理等模块. 从Subsonic到Entity Framework Subsonic最早发布 ...

  2. AppBox升级进行时 - Entity Framework的增删改查

    AppBox 是基于 FineUI 的通用权限管理框架,包括用户管理.职称管理.部门管理.角色管理.角色权限管理等模块. Entity Framework新增数据 以新增用户为例,作为对比,先来看下使 ...

  3. AppBox升级进行时 - 关联表查询与更新(Entity Framework)

    AppBox 是基于 FineUI 的通用权限管理框架,包括用户管理.职称管理.部门管理.角色管理.角色权限管理等模块. 关联表的查询操作 使用 Include 方法,我们可以在一次数据库查询中将关联 ...

  4. AppBox升级进行时 - Attach陷阱(Entity Framework)

    AppBox 是基于 FineUI 的通用权限管理框架,包括用户管理.职称管理.部门管理.角色管理.角色权限管理等模块. Attach方法 前面我们已经多次使用Attach方法,上一次使用Attach ...

  5. AppBox升级进行时 - 如何向OrderBy传递字符串参数(Entity Framework)

    AppBox 是基于 FineUI 的通用权限管理框架,包括用户管理.职称管理.部门管理.角色管理.角色权限管理等模块. Entity Framework提供的排序功能 再来回顾一下上篇文章,加载用户 ...

  6. AppBox升级进行时 - Any与All的用法(Entity Framework)

    AppBox 是基于 FineUI 的通用权限管理框架,包括用户管理.职称管理.部门管理.角色管理.角色权限管理等模块. 属于某个角色的用户列表(Any的用法) 使用Subsonic,我们有两种方法获 ...

  7. docker跨主机通信扁平化网络的设计与实现

    端口映射.ovs. fannel,weave 1.使用网桥实现跨主机容器连接 使用Open vSwitch实现跨主机容器连接

  8. 扁平化设计的最新趋势 – 长阴影(Long Shadow)

    随着互联网的发展,网页设计变得越来越复杂,如今设计的外观和感觉实现网站功能说使用的开发技术一样重要.互联网的功能远远不只是基本的信息共享,现在人们对网站的期望是远远大于几年前的. 如今,HTML5 & ...

  9. Flatty Shadow图标自动产生器——在线生成各种扁平化 ICON

    在扁平化风格越来越流行的今天,网页.软件界面和图标的设计大都采用了扁平化风格.特别是扁平化图标的设计,摒弃了一切3D元素的设计,阴影.纹理.透视神马的统统不要,让图标简洁高效,富有现代感. 今天给大家 ...

随机推荐

  1. js圣诞节倒计时网页

    在线预览:http://keleyi.com/keleyi/phtml/jstexiao/17.htm 以下是代码: <!DOCTYPE html> <html xmlns=&quo ...

  2. JS中用new创建对象与不用new创建对象区别:

    function classA() { console.log(this); var that = this == window ? {} : this; that.name = "clas ...

  3. Ajax表单异步上传(包括文件域)

    起因 做前台页面时,需要调用WebAPI的Post请求,发送一些字段和文件(相当于把表单通过ajax异步发送出去,得到返回结果),然后得到返回值判断是否成功. 尝试 先是尝试了一下 "jQu ...

  4. [Android]Android端ORM框架——RapidORM(v1.0)

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4748077.html  Android上主流的ORM框架有很多 ...

  5. iOS使用Zbar扫描二维码

    iOS使用Zbar扫描二维码 标签(空格分隔):二维码扫描 iOS Zbar64位 正文: 首先下载一个支持64位系统的ZbarSDK的包,保存在了我的云盘里,地址:ZbarSDK 把文件拖到工程里面 ...

  6. iOS百度地图SDK集成详细步骤

    1.iOS百度地图下载地址 http://developer.baidu.com/map/index.php?title=iossdk/sdkiosdev-download 根据需要选择不同的版本  ...

  7. C#中Split用法

    1.用字符串分隔:  using System.Text.RegularExpressions; string str="aaajsbbbjsccc"; string[] sArr ...

  8. SQL SERVER 2012/2014 链接到 SQL SERVER 2000的各种坑

    本文总结一下SQL SERVER 2012/2014链接到SQL SERVER 2000的各种坑,都是在实际应用中遇到的疑难杂症.可能会有人说怎么还在用SQL SERVER 2000,为什么不升级呢? ...

  9. LoadRunner:视频教程、课件

    LoadRunner 视频教程地址: 51 自学网LoadRunner入门视频教程 (这个网站的网址粘不上来,可能与博客园有过节吧)视频中的课件下载地址:链接: http://pan.baidu.co ...

  10. SQLite学习笔记(七)&&事务处理

    说到事务一定会提到ACID,所谓事务的原子性,一致性,隔离性和持久性.对于一个数据库而言,通常通过并发控制和故障恢复手段来保证事务在正常和异常情况下的ACID特性.sqlite也不例外,虽然简单,依然 ...