XAF之自定义登录窗口

来源:互联网 发布:圣贝口腔 知乎 编辑:程序博客网 时间:2024/04/29 16:59

        当使用Standard Authentication验证类型,默认的登录窗口包含两个编辑框:用户名和密码。而本文讲述怎样自定义登录窗口,窗口包含一个下拉式列表选择company,另一个下拉式列表选择该company的employee,还有一个密码输入框。


自定义登录窗口,有以下两种方法:

a.继承AuthenticationStandardLogonParameters类,添加要在登录窗显示的额外属性。然后,可以用安全系统的LogonParameters属性访问特定的登录参数。然而,验证机制仍只使用用户名和密码。所以,若要对额外属性进行验证,需要继承AuthenticationStandard类并重写Authenticate方法。别忘了在Application Designer中指定自定义的登录参数类:

b.实现一个LogonParameters类(不从AuthenticationStandardLogonParameters类继承),添加额外属性。这种情况下,内置的AuthenticationStandard无法执行验证,所以还必须实现自定义的验证策略:继承AuthenticationBase类。

这里,我们使用第二种方法。

实现Employee和Company类

        由于Employee必须支持安全系统,故需要继承BasicUser类。

using System;using System.Collections.Generic;using System.Text;using DevExpress.Persistent.BaseImpl;using DevExpress.Xpo;using DevExpress.Persistent.Base;using DevExpress.ExpressApp.Utils;using DevExpress.Data.Filtering;using System.ComponentModel;namespace AccessDatabaseFromLogonForm.Module {    [DefaultClassOptions(), System.ComponentModel.DefaultProperty("UserName")]public class Employee : SimpleUser {private Company company;        public Employee(Session session)            : base(session) {        }        [Association("Company-Employees", typeof(Company))]        public Company Company {            get { return company; }set {SetPropertyValue("Company", ref company, value);}        }    }}
using System;using DevExpress.Data.Filtering;using DevExpress.Xpo;using DevExpress.ExpressApp;using DevExpress.Persistent.Base;using DevExpress.Persistent.BaseImpl;using DevExpress.Persistent.Validation;using DevExpress.ExpressApp.Utils;namespace AccessDatabaseFromLogonForm.Module {    [DefaultClassOptions()]    public class Company : BaseObject {        public Company(Session session)            : base(session) {        }        private string name;        public string Name {            get { return name; }set {SetPropertyValue("Name", ref name, value);}        }        [Association("Company-Employees", typeof(Employee))]        public XPCollection Employees {            get { return GetCollection("Employees"); }        }    }}
实现MyLogonParameters类
//实现ISupportResetLogonParameters接口,不必重启程序实现登录和注销    //在persistent类中,可以在属性setter中使用SetPropertyValue或OnChanged,但MyLogonParameters不是    //从BaseObject继承而来,故只能实现INotifyPropertyChanged接口[NonPersistent]public class MyLogonParameters : INotifyPropertyChanged, ISupportResetLogonParameters {        private IObjectSpace objectSpace;        //为避免在登录窗口新建Employee和Company,需要设置AvailableCompanies和AvailableUsers只读        private ReadOnlyCollection<Company> availableCompanies;        private XPCollection<Employee> availableUsers;        private Company company;        private Employee employee;        private string password;        private void OnPropertyChanged(string propertyName) {            if(PropertyChanged != null) {                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));            }        }        //显示的Employee要对于其Company,故为availableUsers添加了一个Criteria        private void RefreshAvailableUsers() {            if(availableUsers == null) {                return;            }            availableUsers.Criteria = new BinaryOperator("Company", Company);            if(employee != null && availableUsers.IndexOf(employee) == -1) {                Employee = null;            }            else {                OnPropertyChanged("Employee");            }        }        [Browsable(false)]        public IObjectSpace ObjectSpace {            get { return objectSpace; }            set { objectSpace = value; }        }        //设置为ReadOnlyCollection,只读集合        [Browsable(false)]        public ReadOnlyCollection<Company> AvailableCompanies {            get {                if (objectSpace == null) {                    throw new InvalidOperationException("objectSpace is null");                }                if (availableCompanies == null) {availableCompanies = new ReadOnlyCollection<Company>(ObjectSpace.GetObjects<Company>(null));}                return availableCompanies;            }        }        [Browsable(false)]        public XPCollection<Employee> AvailableUsers {            get {                if (availableUsers == null) {availableUsers = (XPCollection<Employee>)ObjectSpace.GetObjects<Employee>();                    //设置availableUsers只读,不允许绑定的control增/删数据                    availableUsers.BindingBehavior = CollectionBindingBehavior.AllowNone;                    RefreshAvailableUsers();                }                return availableUsers;            }        }        //DataSourceProperty表示Company依赖于于属性AvailableCompanies,非常类似于PersistentAlias特性        //但PersistentAlias是对属性的高级”重命名“,DataSourceProperty是属性和数据绑定的关系        //ImmediatePostData表示当Company数据变化后,立即刷新UI        [DataSourceProperty("AvailableCompanies"), ImmediatePostData]        public Company Company {            get { return company; }            set {                company = value;                RefreshAvailableUsers();            }        }[DataSourceProperty("AvailableUsers"), ImmediatePostData]        public Employee Employee {            get { return employee; }            set {                employee = value;                OnPropertyChanged("Employee");            }        }        [PasswordPropertyText(true)]        public string Password {            get { return password; }            set { password = value; }        }        public void Reset() {            objectSpace = null;            availableCompanies = null;            availableUsers = null;            company = null;            employee = null;            password = null;        }        public event PropertyChangedEventHandler PropertyChanged;    }

在Program.cs 文件中创建AvailableUsers 和 AvailableCompanies 的ObjectSpaced,并订阅CreateCustomLogonWindowObjectSpace事件

static void Main() {//...AccessDatabaseFromLogonFormWindowsFormsApplication application =new AccessDatabaseFromLogonFormWindowsFormsApplication();application.CreateCustomLogonWindowObjectSpace +=new EventHandler<CreateCustomLogonWindowObjectSpaceEventArgs>(application_CreateCustomLogonWindowObjectSpace);//...}static void application_CreateCustomLogonWindowObjectSpace(object sender,CreateCustomLogonWindowObjectSpaceEventArgs e) {e.ObjectSpace = ((XafApplication)sender).CreateObjectSpace();((MyLogonParameters)e.LogonParameters).ObjectSpace = e.ObjectSpace;}

实现MyAuthentication类

       继承AuthenticationBase类,并重写以下方法:

Authenticate

      验证时调用。验证时比对数据库里的信息和logon parameter的值。

ClearSecuredLogonParameters

     清除logon parameters,防止在程序里访问它们,这样就隐藏了安全信息。

GetBusinessClasses

      返回要添加到Application Model 中的bussiness classese。如果不返回LogonParameters,则不会在登录窗口中显示该视图。

AskLogonParametersViaUI

     如果需要显示登录窗口获取用户的logon parameters,则返回true。若从其他地方获取logon parameters,如系统活动文件夹,则返回false。

LogonParameters

      返回代表当前logon parameters的对象。

IsLogoffEnabled

     是否允许“注销”操作。当前仅在ASP.NET可用。

public class MyAuthentication : AuthenticationBase, IAuthenticationStandard {private MyLogonParameters logonParameters;        //创建一个LogonParameters对象public MyAuthentication() {logonParameters = new MyLogonParameters();}        //清除登录信息public override void ClearSecuredLogonParameters() {logonParameters.Password = "";base.ClearSecuredLogonParameters();}        //验证登录,正确则返回该登录用户public override object Authenticate(DevExpress.ExpressApp.IObjectSpace objectSpace) {if(logonParameters.Employee == null) {throw new ArgumentNullException("User");}            //比对密码if(!logonParameters.Employee.ComparePassword(logonParameters.Password)){    throw new AuthenticationException(logonParameters.Employee.UserName, "Wrong password");}return objectSpace.GetObject(logonParameters.Employee);}public override IList<Type> GetBusinessClasses() {return new Type[] { typeof(MyLogonParameters) };}public override bool AskLogonParametersViaUI {get {return true;}}public override object LogonParameters {get { return logonParameters; }}public override bool IsLogoffEnabled {get { return true; }}}
将自定义的这些类传递给系统

          在Application Designer 中,只能添加内置的AuthenticationStandard策略,所以只能在代码中添加MyAuthentication类。WinForm工程里的Main方法中添加:

AccessDatabaseFromLogonFormWindowsFormsApplication application =new AccessDatabaseFromLogonFormWindowsFormsApplication();application.Security = new SecuritySimple<Employee>(new MyAuthentication());



原创粉丝点击