XAF-如何实现自定义权限系统用户对象

2023-07-12,,

本示例使用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-如何实现自定义权限系统用户对象的相关教程结束。

《XAF-如何实现自定义权限系统用户对象.doc》

下载本文的Word格式文档,以方便收藏与打印。