XAF之自定义登录窗口

翻译 2012年03月26日 16:14: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());



相关文章推荐

iphone开发我的新浪微博客户端-用户登录自定义弹出窗口篇(1.2)

本篇的目的是开发一个自定义的弹出对话窗口组件,就是上面图6中半透明的信息提示窗口,其实系统类库中已经有UIActionSheet、UIAlertView能做到这样的功能组件,但是显示外观不怎么美观而且...

iphone开发我的新浪微博客户端-用户登录自定义弹出窗口篇(1.2)

本篇的目的是开发一个自定义的弹出对话窗口组件,就是上面图6中半透明的信息提示窗口,其实系统类库中已经有UIActionSheet、UIAlertView能做到这样的功能组件,但是显示外观不怎么美观而且...
  • mkhgg
  • mkhgg
  • 2011年08月31日 16:41
  • 409

FLTK自定义拖拽控件实现窗口分割

  • 2017年09月21日 20:44
  • 8.42MB
  • 下载

自定义弹出窗口

  • 2012年10月14日 12:26
  • 79KB
  • 下载

XAF之点击Navigation Control弹出新建对象窗口

当单击navigation control的item时,执行New(NewObjectViewController.NewObjectAction)按钮。      先新建一个DemoIss...
  • qjpcpu
  • qjpcpu
  • 2012年03月30日 20:30
  • 962

自定义透明窗口

  • 2015年06月20日 17:58
  • 1.56MB
  • 下载

Android手机UI设计---”知乎“界面外观模仿篇(二)---在Fragment里使用自定义listview以及popupwindow弹出窗口

这是接着上一篇博客的Android手机UI设计—“知乎”模仿的界面设计二。任务目标:较为完善的模仿“知乎”的 私信 界面。PS:这个我是用Android Studio2.3做的。由于自己初学Andro...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:XAF之自定义登录窗口
举报原因:
原因补充:

(最多只允许输入30个字)