• 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); }
        }
    }

    Expanded 实现接口: 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
    }

    Expanded 实现 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验证方式,则不需要实现这个接口.

    Expanded 支持IAuthenticationActiveDirectoryUser 接口,为活动目录验证方式提供支持

     
    using DevExpress.Persistent.Base.Security;
    // ... 
    public class Employee : Person, ISecurityUser, 
        IAuthenticationStandardUser, IAuthenticationActiveDirectoryUser {
        // ... 
    }

    如果不想支持 AuthenticationActiveDirectory 验证方式则不需要实现此步骤.

    Expanded 支持 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>(); }
        } 
    }

    Expanded 支持 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
    }

    其实这个接口还是挺有用的,上面的代码是从角色中读取权限的数据.

    Expanded 支持 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
    }

    Expanded 应用创建的自定义类

     

     如图所示,在属性栏中设置自定义的类.

    Expanded 创建管理员账号

     如果你决定使用活动目录验证方式,需要跳过这里.
    在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();
    }

    就是说,在数据库结构创建(或更新)完成后,执行上面的代码.

    Expanded 运行

     win:
     

    Expanded 只显示当前用户的的"任务"

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

    结果如下.

     
    如果你只是想为用户加几个属性,则不需要上面这么麻烦
    直接继承自PermissionPolicyUser即可,然后加属性.当然,不要忘记
    这一步的应用类就好了.
     
  • 相关阅读:
    【bzoj2190】: [SDOI2008]仪仗队 数论-欧拉函数
    【bzoj2751】[HAOI2012]容易题(easy) 数论-快速幂
    【bzoj2186】: [Sdoi2008]沙拉公主的困惑 数论-欧拉函数
    这里会有你想要的,已收录css , js相关文章
    Vue源码解析--实现一个指令解析器 Compile
    九宫格抽奖
    12行代码简单实现跑马灯文字匀速滚动
    滑弯曲弧形效果的插件-arctext.js改造
    几种拼图小游戏封装
    倒计时
  • 原文地址:https://www.cnblogs.com/foreachlife/p/6683328.html
Copyright © 2020-2023  润新知