这里,我只是以一个例子,说一下简单权限控制,通过这个例子,大家可以设计庞大的权限管理层,把权限控制封装到数据库访问层,这样程序员就不用再写权限判断的代码了
首先,先看看我数据库DBContext的定义
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace WebApplication1 { public class SysDB:Test.DB.TestDB { public SysDB() : base(@"data source=""F:SqliteLinqTestTestDB""", EntityDB.DatabaseType.Sqlite) { } } }
程序员读取UserInfo表,代码是这样
var db = new SysDB(); var datasource = db.UserInfo.ToArray();
现在,有这样的需求,当前登录用户如果是admin,那么可以读取UserInfo所有字段的值,否则,只能读取id、UserName这两个字段值,并且不能显示属于财务部的user
通常,如果没有权限控制层,程序员需要这样写代码
var db = new SysDB(); IQueryable<Test.UserInfo> query; if (CurrentUserName == "admin") { query = db.UserInfo; } else { query = from m in db.UserInfo where db.Department.Any(p=>p.Name == "财务部" && p.id == m.DepartmentID) == false select new Test.UserInfo { id = m.id, UserName = m.UserName }; } var datasource = query.ToArray();
如果每个页面,甚至每个控件绑定数据的时候,都需要程序员这样写代码做过滤,首先,累死程序员,其次,程序员如果忘记做判断,系统就存在了权限漏洞
现在,我就要把这条规则,封装到数据库访问层,我只需要在DBContext里面做一下重载
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace WebApplication1 { public class SysDB:Test.DB.TestDB { public SysDB() : base(@"data source=""F:SqliteLinqTestTestDB""", EntityDB.DatabaseType.Sqlite) { } public override IQueryable<Test.UserInfo> UserInfo { get { IQueryable<Test.UserInfo> query; if (Helper.CurrentUserName == "admin") { query = base.UserInfo; } else { query = from m in base.UserInfo where this.Department.Any(p => p.Name == "财务部" && p.id == m.DepartmentID) == false select new Test.UserInfo { id = m.id, UserName = m.UserName }; } return query; } } } }
OK,封装完毕了,以后,程序员读取UserInfo表,代码还是这样就可以了
var db = new SysDB();
var datasource = db.UserInfo.ToArray();
而且,不管程序员加任何的where条件,都不会读出属于财务部的user数据,真正做到把权限封死在数据库访问层了
其次,像我前面文章里面提到的那些支持Entity对象的控件,如EntityGridView、TextBoxList等自动绑定数据的控件,由于它们底层也是访问DBContext对象,所以也是受到这个权限的约束
注意:像下面这种写法
query = from m in base.UserInfo where this.Department.Any(p => p.Name == "财务部" && p.id == m.DepartmentID) == false select new Test.UserInfo { id = m.id, UserName = m.UserName };
select new Test.UserInfo 这样的写法,在标准的Entity Framework 6 里面是报错的,因为new的类型不能和表对象的类型相同,这种写法,只有在我前面文章介绍的Mr.E生成的数据库dll可以这样写