DevExpress_XPO_自定义安全对象(用户、角色、操作权限)

我们将学习如何创建自定义安全对象(包括角色、用户和权限)。

注:这个例子只适用于XPO应用程序。(要在EF应用程序中使用),请自行修改。

完整项目演示网址请参考官网。

实现自定义的角色和用户对象

  •  角色继承PermissionPolicyRole类,使用附加属性CanExport。
 1 using DevExpress.Persistent.BaseImpl.PermissionPolicy;
 2 // ... 
 3 [DefaultClassOptions, ImageName("BO_Role")]
 4 public class ExtendedSecurityRole : PermissionPolicyRole {
 5     public ExtendedSecurityRole(Session session) : base(session) { }
 6     public bool CanExport {
 7         get { return GetPropertyValue<bool>("CanExport"); }
 8         set { SetPropertyValue<bool>("CanExport", value); }
 9     }
10 }
  •   按照如下方式布局页面。
  • 下面代码演示了自定义用户对象的实现。
 1 using DevExpress.Persistent.BaseImpl.PermissionPolicy;
 2 // ... 
 3 [DefaultClassOptions, ImageName("BO_Employee")]
 4 public class Employee : PermissionPolicyUser {
 5     public Employee(Session session)
 6         : base(session) { }
 7     [Association("Employee-Task")]
 8     public XPCollection<Task> Tasks {
 9         get { return GetCollection<Task>("Tasks");  }
10     }
11 }
12 [DefaultClassOptions, ImageName("BO_Task")]
13 public class Task : BaseObject {
14     public Task(Session session)
15         : base(session) { }
16     private string subject;
17     public string Subject {
18         get { return subject; }
19         set { SetPropertyValue("Subject", ref subject, value); }
20     }
21     private DateTime dueDate;
22     public DateTime DueDate {
23         get { return dueDate; }
24         set { SetPropertyValue("DueDate", ref dueDate, value); }
25     }
26     private Employee assignedTo;
27     [Association("Employee-Task")]
28     public Employee AssignedTo {
29         get { return assignedTo; }
30         set { SetPropertyValue("AssignedTo", ref assignedTo, value); }
31     }
32 }
  •  调用应用程序设计器,并按照下图所示拖拽主键。修改AuthenticationStandard的RoleType和UserType。

 实现自定义操作权限和权限请求

  • 继承接口IOperationPermission。
1 using DevExpress.ExpressApp.Security;
2 // ... 
3 public class ExportPermission : IOperationPermission {
4     public string Operation { 
5         get { return "Export"; }
6     }
7 }
  •  要实现添加权限请求,需要实现IPermissionRequest接口。
1 public class ExportPermissionRequest : IPermissionRequest {
2     public object GetHashObject() {
3         return this.GetType().FullName;
4     }
5 }

在安全策略中实现权限请求处理器

  • 所有权限请求都应该在安全策略中注册适当的权限请求处理器。继承PermissionRequestProcessorBase类,并将权限请求类型作为祖先类的泛型参数传递,以实现一个类作为处理器。
 1 public class ExportPermissionRequestProcessor : 
 2     PermissionRequestProcessorBase<ExportPermissionRequest> {
 3     private IPermissionDictionary permissions;
 4     public ExportPermissionRequestProcessor(IPermissionDictionary permissions) {
 5         this.permissions = permissions;
 6     }
 7     public override bool IsGranted(ExportPermissionRequest permissionRequest) {
 8         return (permissions.FindFirst<ExportPermission>() != null);
 9     }
10 }
  •  在事件处理程序中,将ExportPermission对象传递给PermissionDictionary。

Win版本(Global.asax.cs (Global.asax.vb))

 1 ((SecurityStrategy)winApplication.Security).CustomizeRequestProcessors +=
 2     delegate(object sender, CustomizeRequestProcessorsEventArgs e) {
 3         List<IOperationPermission> result = new List<IOperationPermission>();
 4         SecurityStrategyComplex security = sender as SecurityStrategyComplex;
 5         if (security != null) {
 6             Employee user = security.User as Employee;
 7             if (user != null) {
 8                 foreach (ExtendedSecurityRole role in user.Roles) {
 9                     if (role.CanExport) {
10                         result.Add(new ExportPermission());
11                     }
12                 }
13             }
14         }
15         IPermissionDictionary permissionDictionary = new PermissionDictionary((IEnumerable<IOperationPermission>)result);
16         e.Processors.Add(typeof(ExportPermissionRequest), new ExportPermissionRequestProcessor(permissionDictionary));
17     }; 
18 winApplication.Setup();
19 winApplication.Start();

     ASP.NET版本(Program.cs (Program.vb))

 1 ((SecurityStrategy)WebApplication.Instance.Security).CustomizeRequestProcessors +=
 2     delegate(object s, CustomizeRequestProcessorsEventArgs args) {
 3         List<IOperationPermission> result = new List<IOperationPermission>();
 4         SecurityStrategyComplex security = s as SecurityStrategyComplex;
 5         if (security != null) {
 6             Employee user = security.User as Employee;
 7             if (user != null) {
 8                 foreach (ExtendedSecurityRole role in user.Roles) {
 9                     if (role.CanExport) {
10                         result.Add(new ExportPermission());
11                     }
12                 }
13             }
14         }
15         IPermissionDictionary permissionDictionary = new PermissionDictionary((IEnumerable<IOperationPermission>)result);
16         args.Processors.Add(typeof(ExportPermissionRequest), new ExportPermissionRequestProcessor(permissionDictionary));
17     };
18 WebApplication.Instance.Setup();
19 WebApplication.Instance.Start();

 Application Server

 1 static void Main(string[] args) {
 2     // ... 
 3     Func<IDataServerSecurity> dataServerSecurityProvider = () => {
 4         SecurityStrategyComplex security = new SecurityStrategyComplex(
 5             typeof(Employee), typeof(ExtendedSecurityRole), new AuthenticationStandard());
 6         security.CustomizeRequestProcessors +=
 7             delegate(object sender, CustomizeRequestProcessorsEventArgs e) {
 8                 List<IOperationPermission> result = new List<IOperationPermission>();
 9                 if (security != null) {
10                     Employee user = security.User as Employee;
11                     if (user != null) {
12                         foreach (ExtendedSecurityRole role in user.Roles) {
13                             if (role.CanExport) {
14                                 result.Add(new ExportPermission());
15                             }
16                         }
17                     }
18                 }
19                 IPermissionDictionary permissionDictionary = new PermissionDictionary((IEnumerable<IOperationPermission>)result);
20                 e.Processors.Add(typeof(ExportPermissionRequest), new ExportPermissionRequestProcessor(permissionDictionary));
21             }; 
22         return security;
23     };
24     // ... 
25 }

初始化方法说明

1 WcfDataServerHelper.AddKnownType(typeof(ExportPermissionRequest));

ExportController控制器中考虑自定义权限

自定义中,代码如下(不允许导出数据的用户禁用控制器):

 1 public class SecuredExportController : ViewController {
 2     protected override void OnActivated() {
 3         base.OnActivated();
 4         ExportController controller = Frame.GetController<ExportController>();
 5         if (controller != null) {
 6             controller.ExportAction.Executing += ExportAction_Executing;
 7             if(SecuritySystem.Instance is IRequestSecurity) {
 8                 controller.Active.SetItemValue("Security", 
 9                     SecuritySystem.IsGranted(new ExportPermissionRequest()));
10             }
11         }
12     }
13     void ExportAction_Executing(object sender, System.ComponentModel.CancelEventArgs e) {
14         SecuritySystem.Demand(new ExportPermissionRequest());
15     }
16 }

 添加演示数据

 1 public class Updater : ModuleUpdater {
 2     public Updater(IObjectSpace objectSpace, Version currentDBVersion) : 
 3         base(objectSpace, currentDBVersion) { }
 4     public override void UpdateDatabaseAfterUpdateSchema() {
 5         base.UpdateDatabaseAfterUpdateSchema();
 6         ExtendedSecurityRole defaultRole = CreateUserRole();
 7         ExtendedSecurityRole administratorRole = CreateAdministratorRole();
 8         ExtendedSecurityRole exporterRole = CreateExporterRole();
 9         Employee userAdmin = ObjectSpace.FindObject<Employee>(new BinaryOperator("UserName", "Admin"));
10         if (userAdmin == null) {
11             userAdmin = ObjectSpace.CreateObject<Employee>();
12             userAdmin.UserName = "Admin";
13             userAdmin.IsActive = true;
14             userAdmin.SetPassword("");
15             userAdmin.Roles.Add(administratorRole);
16         }
17         Employee userSam = ObjectSpace.FindObject<Employee>(new BinaryOperator("UserName", "Sam"));
18         if (userSam == null) {
19             userSam = ObjectSpace.CreateObject<Employee>();
20             userSam.UserName = "Sam";
21             userSam.IsActive = true;
22             userSam.SetPassword("");
23             userSam.Roles.Add(exporterRole);
24             userSam.Roles.Add(defaultRole);
25         }
26         Employee userJohn = ObjectSpace.FindObject<Employee>(new BinaryOperator("UserName", "John"));
27         if (userJohn == null) {
28             userJohn = ObjectSpace.CreateObject<Employee>();
29             userJohn.UserName = "John";
30             userJohn.IsActive = true;
31             userJohn.Roles.Add(defaultRole);
32             for (int i = 1; i <= 10; i++) {
33                 string subject = string.Format("Task {0}",i);
34                 Task task = ObjectSpace.FindObject<Task>(new BinaryOperator("Subject", subject));
35                 if (task == null) {
36                     task = ObjectSpace.CreateObject<Task>();
37                     task.Subject = subject;
38                     task.DueDate = DateTime.Today;
39                     task.Save();
40                     userJohn.Tasks.Add(task);
41                 }
42             }
43         }
44         ObjectSpace.CommitChanges();
45     }
46     private ExtendedSecurityRole CreateAdministratorRole() {
47         ExtendedSecurityRole administratorRole = ObjectSpace.FindObject<ExtendedSecurityRole>(
48             new BinaryOperator("Name", SecurityStrategyComplex.AdministratorRoleName));
49         if (administratorRole == null) {
50             administratorRole = ObjectSpace.CreateObject<ExtendedSecurityRole>();
51             administratorRole.Name = SecurityStrategyComplex.AdministratorRoleName;
52             administratorRole.IsAdministrative = true;
53         }
54         return administratorRole;
55     }
56     private ExtendedSecurityRole CreateExporterRole() {
57         ExtendedSecurityRole exporterRole = ObjectSpace.FindObject<ExtendedSecurityRole>(
58             new BinaryOperator("Name", "Exporter"));
59         if (exporterRole == null) {
60             exporterRole = ObjectSpace.CreateObject<ExtendedSecurityRole>();
61             exporterRole.Name = "Exporter";
62             exporterRole.CanExport = true;
63         }
64         return exporterRole;
65     }
66     private ExtendedSecurityRole CreateUserRole() {
67         ExtendedSecurityRole userRole = ObjectSpace.FindObject<ExtendedSecurityRole>(
68             new BinaryOperator("Name", "Default"));
69         if (userRole == null) {
70             userRole = ObjectSpace.CreateObject<ExtendedSecurityRole>();
71             userRole.Name = "Default";
72             userRole.SetTypePermission<Task>(SecurityOperations.FullAccess, SecurityPermissionState.Allow);
73             userRole.SetTypePermission<Employee>(SecurityOperations.ReadOnlyAccess, SecurityPermissionState.Allow);
74             userRole.AddObjectPermission<PermissionPolicyUser>(SecurityOperations.ReadOnlyAccess,
75                  "[Oid] = CurrentUserId()", SecurityPermissionState.Allow);
76         }
77         return userRole;
78     }
79 }

 效果展示

运行WinForm或者ASP.NET,登录“Admin”用户,打开用户的详细视图。

   登录“Sam”用户,“Export To”是可用的;登录“John”,“Export To”不是可用的。

参考网址

[1] https://documentation.devexpress.com/eXpressAppFramework/113384/Task-Based-Help/Security/How-to-Implement-Custom-Security-Objects-Users-Roles-Operation-Permissions

[2]完整项目演示:www.devexpress.com/example=E3794

[3] PermissionPolicyRole 的属性信息:https://documentation.devexpress.com/eXpressAppFramework/DevExpress.Persistent.BaseImpl.PermissionPolicy.PermissionPolicyRole.members

posted @ 2019-09-11 09:36  陆陆无为而治者  阅读(634)  评论(0编辑  收藏  举报