XAF-如何实现自定义权限系统用户对象
本示例使用XPO.
新建一个XAF项目.填加两个类进来:
[DefaultClassOptions] public class Employee : Person { public Employee(Session session) : base(session) { } [Association("Employee-Task")] public XPCollection<EmployeeTask> OwnTasks { get { return GetCollection<EmployeeTask>("OwnTasks"); } } } [DefaultClassOptions, ImageName("BO_Task")] public class EmployeeTask : Task { public EmployeeTask(Session session) : base(session) { } private Employee owner; [Association("Employee-Task")] public Employee Owner { get { return owner; } set { SetPropertyValue("Owner", ref owner, value); } } }
实现接口: ISecurityUser
填加引用: DevExpress.ExpressApp.Security.v16.2.dll 程序集
using DevExpress.ExpressApp.Security; using DevExpress.Persistent.Validation; // ... public class Employee : Person, ISecurityUser { // ... #region ISecurityUser Members private bool isActive = true; public bool IsActive { get { return isActive; } set { SetPropertyValue("IsActive", ref isActive, value); } } private string userName = String.Empty; [RuleRequiredField("EmployeeUserNameRequired", DefaultContexts.Save)] [RuleUniqueValue("EmployeeUserNameIsUnique", DefaultContexts.Save, "The login with the entered user name was already registered within the system.")] public string UserName { get { return userName; } set { SetPropertyValue("UserName", ref userName, value); } } #endregion }
实现 IAuthenticationStandardUser 接口
using System.ComponentModel; using DevExpress.Persistent.Base.Security; // ... public class Employee : Person, ISecurityUser, IAuthenticationStandardUser { // ... #region IAuthenticationStandardUser Members private bool changePasswordOnFirstLogon; public bool ChangePasswordOnFirstLogon { get { return changePasswordOnFirstLogon; } set { SetPropertyValue("ChangePasswordOnFirstLogon", ref changePasswordOnFirstLogon, value); } } private string storedPassword; [Browsable(false), Size(SizeAttribute.Unlimited), Persistent, SecurityBrowsable] protected string StoredPassword { get { return storedPassword; } set { storedPassword = value; } } public bool ComparePassword(string password) { return PasswordCryptographer.VerifyHashedPasswordDelegate(this.storedPassword, password); } public void SetPassword(string password) { this.storedPassword = PasswordCryptographer.HashPasswordDelegate(password); OnChanged("StoredPassword"); } #endregion }
如果不想支持AuthenticationStandard验证方式,则不需要实现这个接口.
支持IAuthenticationActiveDirectoryUser 接口,为活动目录验证方式提供支持
using DevExpress.Persistent.Base.Security; // ... public class Employee : Person, ISecurityUser, IAuthenticationStandardUser, IAuthenticationActiveDirectoryUser { // ... }
如果不想支持 AuthenticationActiveDirectory 验证方式则不需要实现此步骤.
支持 ISecurityUserWithRoles 接口.即,让用户支持角色
[DefaultClassOptions] public class Employee : Person, ISecurityUser, IAuthenticationStandardUser, IAuthenticationActiveDirectoryUser, ISecurityUserWithRoles { // ... #region ISecurityUserWithRoles Members IList<ISecurityRole> ISecurityUserWithRoles.Roles { get { IList<ISecurityRole> result = new List<ISecurityRole>(); foreach (EmployeeRole role in EmployeeRoles) { result.Add(role); } return result; } } #endregion [Association("Employees-EmployeeRoles")] [RuleRequiredField("EmployeeRoleIsRequired", DefaultContexts.Save, TargetCriteria = "IsActive", CustomMessageTemplate = "An active employee must have at least one role assigned")] public XPCollection<EmployeeRole> EmployeeRoles { get { return GetCollection<EmployeeRole>("EmployeeRoles"); } } }
定义了一个角色,是继承自系统内置的:
using DevExpress.Persistent.BaseImpl.PermissionPolicy; // ... [ImageName("BO_Role")] public class EmployeeRole : PermissionPolicyRoleBase, IPermissionPolicyRoleWithUsers { public EmployeeRole(Session session) : base(session) { } [Association("Employees-EmployeeRoles")] public XPCollection<Employee> Employees { get { return GetCollection<Employee>("Employees"); } } IEnumerable<IPermissionPolicyUser> IPermissionPolicyRoleWithUsers.Users { get { return Employees.OfType<IPermissionPolicyUser>(); } } }
支持 IPermissionPolicyUser 接口,为实现每个用户提供权限数据
using DevExpress.ExpressApp.Utils; // ... [DefaultClassOptions] public class Employee : Person, ISecurityUser, IAuthenticationStandardUser, IAuthenticationActiveDirectoryUser, IPermissionPolicyUser { // ... #region IPermissionPolicyUser Members IEnumerable<IPermissionPolicyRole> IPermissionPolicyUser.Roles { get { return EmployeeRoles.OfType<IPermissionPolicyRole>(); } } #endregion }
其实这个接口还是挺有用的,上面的代码是从角色中读取权限的数据.
支持 ICanInitialize 接口
ICanInitialize.Initialize 在 AuthenticationActiveDirectory 验证方式并且设置了 AuthenticationActiveDirectory.CreateUserAutomatically为true时.如果你不需要支持这个自动创建,可以跳过这里.
using DevExpress.ExpressApp; using DevExpress.Data.Filtering; // ... [DefaultClassOptions] public class Employee : Person, ISecurityUser, IAuthenticationStandardUser, IAuthenticationActiveDirectoryUser, IPermissionPolicyUser, ICanInitialize { // ... #region ICanInitialize Members void ICanInitialize.Initialize(IObjectSpace objectSpace, SecurityStrategyComplex security) { EmployeeRole newUserRole = (EmployeeRole)objectSpace.FindObject<EmployeeRole>( new BinaryOperator("Name", security.NewUserRoleName)); if (newUserRole == null) { newUserRole = objectSpace.CreateObject<EmployeeRole>(); newUserRole.Name = security.NewUserRoleName; newUserRole.IsAdministrative = true; newUserRole.Employees.Add(this); } } #endregion }
应用创建的自定义类
如图所示,在属性栏中设置自定义的类.

创建管理员账号
如果你决定使用活动目录验证方式,需要跳过这里.
在module项目的databaseUpdate文件夹中,找到Updater.cs. 重写 ModuleUpdater.UpdateDatabaseAfterUpdateSchema 方法.
using DevExpress.ExpressApp.Security.Strategy; // ... public override void UpdateDatabaseAfterUpdateSchema() { base.UpdateDatabaseAfterUpdateSchema(); EmployeeRole adminEmployeeRole = ObjectSpace.FindObject<EmployeeRole>( new BinaryOperator("Name", SecurityStrategy.AdministratorRoleName)); if (adminEmployeeRole == null) { adminEmployeeRole = ObjectSpace.CreateObject<EmployeeRole>(); adminEmployeeRole.Name = SecurityStrategy.AdministratorRoleName; adminEmployeeRole.IsAdministrative = true; adminEmployeeRole.Save(); } Employee adminEmployee = ObjectSpace.FindObject<Employee>( new BinaryOperator("UserName", "Administrator")); if (adminEmployee == null) { adminEmployee = ObjectSpace.CreateObject<Employee>(); adminEmployee.UserName = "Administrator"; adminEmployee.SetPassword(""); adminEmployee.EmployeeRoles.Add(adminEmployeeRole); } ObjectSpace.CommitChanges(); }
就是说,在数据库结构创建(或更新)完成后,执行上面的代码.
运行
win:

只显示当前用户的的"任务"
应用 ListViewFilterAttribute 特性到EmployeeTask 类,定义一个列表过滤.
CurrentUserId会取得当前用户的id
[ListViewFilter("All Tasks", "")] [ListViewFilter("My Tasks", "[Owner.Oid] = CurrentUserId()")] public class EmployeeTask : Task { // ... }
结果如下.

如果你只是想为用户加几个属性,则不需要上面这么麻烦
直接继承自PermissionPolicyUser即可,然后加属性.当然,不要忘记

这一步的应用类就好了.
XAF开发成品案例参考
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
作者博客: http://www.cnblogs.com/foreachlife
欢迎加入CIIP框架\XAF技术应用交流群: 336090194 群文件中有更多相关工具及文档资料
转载请注明出处。多谢!
欢迎加我微信: admiralcn 或扫码:

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端