本示例使用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即可,然后加属性.当然,不要忘记
这一步的应用类就好了.