XAF开发学习(2)自定义登录验证

最终实现效果:

 

作为XAF学习的第二节,仅仅学习了BO的知识可能难度稍大,只需要按照步骤一步一步完成相关知识后续讲解

1、创建项目时,按下图设置我们可以得到一个默认权限的项目

2、打开web项目或win项目下的WinApplication.cs文件

我们可以看到系统自带了2个验证器,此2个验证器是默认的登录窗体

 

对应下方登录页面

 

3、项目*.Modeule下BusinessObjects文件夹下创建Employee、Company 的BO对象

using DevExpress.Xpo;
using DevExpress.ExpressApp.DC;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl.PermissionPolicy;



[DefaultClassOptions]
[XafDefaultProperty("UserName"), XafDisplayName("员工")]
public class Employee : PermissionPolicyUser
{
    public Employee(Session session) : base(session) { }
    private Company company;
    [Association("Company-Employees")]
    [XafDisplayName("公司")]
    public Company Company
    {
        get { return company; }
        set { SetPropertyValue("Company", ref company, value); }
    }
}
using DevExpress.Xpo;
using DevExpress.ExpressApp.DC;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl; 


[DefaultClassOptions]
[XafDisplayName("公司"), XafDefaultProperty("Name")]
public class Company : BaseObject
{
    public Company(Session session) : base(session) { }
    private string name;

    [XafDisplayName("名称")]
    public string Name
    {
        get { return name; }
        set { SetPropertyValue("Name", ref name, value); }
    }
    [Association("Company-Employees")]
    public XPCollection<Employee> Employees
    {
        get { return GetCollection<Employee>("Employees"); }
    }
} 

4、项目*.Modeule下添加参数类CustomLogonParameters.cs、CustomAuthentication.cs

using System;
using System.ComponentModel;
using System.Runtime.Serialization;
using DevExpress.ExpressApp.DC;
using DevExpress.Persistent.Base;

//……
[DomainComponent, Serializable]
[System.ComponentModel.DisplayName("登录")]                       //登录标题
public class CustomLogonParameters : INotifyPropertyChanged, ISerializable
{
    #region 构造方法
    public CustomLogonParameters() { }

    //ISerializable,序列化
    public CustomLogonParameters(SerializationInfo info, StreamingContext context)
    {
        if (info.MemberCount > 0)
        {
            UserName = info.GetString("UserName");
            Password = info.GetString("Password");
        }
    }
    #endregion

    private Company company;                //公司
    private Employee employee;              //员工
    private string password;                //密码

    [ImmediatePostData]   //值应该尽快传递给绑定对象,但用户更改值时,允许强制更新
    [XafDisplayName("公司")]
    public Company Company
    {
        get { return company; }
        set
        {
            if (value == company) return;
            company = value;
            Employee = null;
            OnPropertyChanged("Company");
        }
    }
    [DataSourceProperty("Company.Employees")]
    [ImmediatePostData] //值应该尽快传递给绑定对象,但用户更改值时,允许强制更新
    [XafDisplayName("员工")]
    public Employee Employee
    {
        get { return employee; }
        set
        {
            if (Company == null) return;
            employee = value;
            if (employee != null)
            {
                UserName = employee.UserName;
            }
            OnPropertyChanged("Employee");
        }
    }
    [Browsable(false)]                  //用户名在登录页面不显示
    [XafDisplayName("用户名")]
    public String UserName { get; set; }
    [PasswordPropertyText(true)]
    [XafDisplayName("密码")]
    public string Password
    {
        get { return password; }
        set
        {
            if (password == value) { return; }
            password = value;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    //属性更改时引发事件页面上能快速更改事件)
    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    [System.Security.SecurityCritical]
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("UserName", UserName);
        info.AddValue("Password", Password);
    }
}
//……

using System;
using DevExpress.ExpressApp;
using DevExpress.Data.Filtering;
using System.Collections.Generic;
using DevExpress.ExpressApp.Security; 
//……

/// <summary>
    /// 自定义登录参数类
    /// </summary>
    public class CustomAuthentication : AuthenticationBase, IAuthenticationStandard
    {
        private CustomLogonParameters customLogonParameters;            //登录参数
        public CustomAuthentication()
        {
            customLogonParameters = new CustomLogonParameters();
        }
        /// <summary>
        /// 注销
        /// </summary>
        public override void Logoff()
        {
            base.Logoff();
            customLogonParameters = new CustomLogonParameters();
        }
        /// <summary>
        /// 重置登录参数
        /// </summary>
        public override void ClearSecuredLogonParameters()
        {
            customLogonParameters.Password = "";
            base.ClearSecuredLogonParameters();
        }
        /// <summary>
        /// 通过比较登录参数与数据库中用户对象的值,进行验证。
        ///
        /// </summary>
        /// <param name="objectSpace">用户数据操作对象空间</param>
        /// <returns>经身份验证的用户</returns>
        public override object Authenticate(IObjectSpace objectSpace)
        {

            Employee employee = objectSpace.FindObject<Employee>(new BinaryOperator("UserName", customLogonParameters.UserName));
            if (employee == null)
            {
                throw new ArgumentNullException("Employee");
            }
            if (!employee.ComparePassword(customLogonParameters.Password))
            {
                throw new AuthenticationException(employee.UserName, "密码错误.");
            }
            return employee;
        }

        /// <summary>
        /// 初始化登录参数
        /// </summary>
        /// <param name="logonParameters">登录参数</param>
        public override void SetLogonParameters(object logonParameters)
        {
            this.customLogonParameters = (CustomLogonParameters)logonParameters;
        }

        /// <summary>
        /// 返回到要添加程序的应用列表
        /// </summary>
        /// <returns></returns>
        public override IList<Type> GetBusinessClasses()
        {
            return new Type[] { typeof(CustomLogonParameters) };
        }
        /// <summary>
        /// 指示登录过程是否是交互式的(通过登录对话框请求登录参数)
        /// </summary>
        public override bool AskLogonParametersViaUI
        {
            get { return true; }
        }

        /// <summary>
        /// 返回登录参数
        /// </summary>
        public override object LogonParameters
        {
            get { return customLogonParameters; }
        }
        /// <summary>
        /// 是否启用注销方法,继承AuthenticationBase
        /// </summary>
        public override bool IsLogoffEnabled
        {
            get { return true; }
        }
}

//……

5、重新打开.Win项目下的WinApplication.cs文件,web版类似

 已经发现我们添加的文件,拖拽替换系统自带的对象

替换后:

对 更改验证Model

6、修改Win项目的启动文件Program.cs 及WinApplication.cs

Program.cs

添加1个方法

  private static void application_CreateCustomLogonWindowObjectSpace(object sender, CreateCustomLogonWindowObjectSpaceEventArgs e)
        {
            e.ObjectSpace = ((XafApplication)sender).CreateObjectSpace(typeof(CustomLogonParameters));
            if (e.ObjectSpace is NonPersistentObjectSpace)
            {
                IObjectSpace objectSpaceCompany = ((XafApplication)sender).CreateObjectSpace(typeof(Company));
                ((NonPersistentObjectSpace)e.ObjectSpace).AdditionalObjectSpaces.Add(objectSpaceCompany);
            }
        }

 在Main函数中调用,应在 winApplication.Setup(); winApplication.Start();代码前添加


            winApplication.CreateCustomLogonWindowObjectSpace +=  application_CreateCustomLogonWindowObjectSpace;

 完整版本如下:

using System;
using System.Configuration;
using System.Windows.Forms;

using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Security;
using DevExpress.ExpressApp.Win;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl;
using DevExpress.XtraEditors;

namespace DXApplication1cc.Win {
    static class Program {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main() {
            DevExpress.ExpressApp.FrameworkSettings.DefaultSettingsCompatibilityMode = DevExpress.ExpressApp.FrameworkSettingsCompatibilityMode.Latest;
#if EASYTEST
            DevExpress.ExpressApp.Win.EasyTest.EasyTestRemotingRegistration.Register();
#endif
            WindowsFormsSettings.LoadApplicationSettings();
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
			DevExpress.Utils.ToolTipController.DefaultController.ToolTipType = DevExpress.Utils.ToolTipType.SuperTip;
            EditModelPermission.AlwaysGranted = System.Diagnostics.Debugger.IsAttached;
            if(Tracing.GetFileLocationFromSettings() == DevExpress.Persistent.Base.FileLocation.CurrentUserApplicationDataFolder) {
                Tracing.LocalUserAppDataPath = Application.LocalUserAppDataPath;
            }
            Tracing.Initialize();
            DXApplication1ccWindowsFormsApplication winApplication = new DXApplication1ccWindowsFormsApplication();
            winApplication.GetSecurityStrategy().RegisterXPOAdapterProviders();
            if(ConfigurationManager.ConnectionStrings["ConnectionString"] != null) {
                winApplication.ConnectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
            }
#if EASYTEST
            if(ConfigurationManager.ConnectionStrings["EasyTestConnectionString"] != null) {
                winApplication.ConnectionString = ConfigurationManager.ConnectionStrings["EasyTestConnectionString"].ConnectionString;
            }
#endif
#if DEBUG
            if(System.Diagnostics.Debugger.IsAttached && winApplication.CheckCompatibilityType == CheckCompatibilityType.DatabaseSchema) {
                winApplication.DatabaseUpdateMode = DatabaseUpdateMode.UpdateDatabaseAlways;
            }
#endif

            winApplication.CreateCustomLogonWindowObjectSpace +=  application_CreateCustomLogonWindowObjectSpace;


            try {
                winApplication.Setup();
                winApplication.Start();
            }
            catch(Exception e) {
                winApplication.StopSplash();
                winApplication.HandleException(e);
            }
        }



        private static void application_CreateCustomLogonWindowObjectSpace(object sender, CreateCustomLogonWindowObjectSpaceEventArgs e)
        {
            e.ObjectSpace = ((XafApplication)sender).CreateObjectSpace(typeof(CustomLogonParameters));
            if (e.ObjectSpace is NonPersistentObjectSpace)
            {
                IObjectSpace objectSpaceCompany = ((XafApplication)sender).CreateObjectSpace(typeof(Company));
                ((NonPersistentObjectSpace)e.ObjectSpace).AdditionalObjectSpaces.Add(objectSpaceCompany);
            }
        }


    }
}

WinApplication.cs  ,打开后右键查看代码

 替换CreateDefaultObjectSpaceProvider方法内的内容为:


            //允许在登录窗口中访问公司、员工数据
            ((SecurityStrategy)Security).AnonymousAllowedTypes.Add(typeof(Company));
            ((SecurityStrategy)Security).AnonymousAllowedTypes.Add(typeof(Employee));

            args.ObjectSpaceProviders.Add(new XPObjectSpaceProvider(args.ConnectionString, args.Connection, false));
            args.ObjectSpaceProviders.Add(new NonPersistentObjectSpaceProvider(TypesInfo, null));

6.1 Web版本(基本与Win类似)

修改文件Global.asax文件

using CustomLogonParametersExample.Module;
using CustomLogonParametersExample.Module.BusinessObjects;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Web;
// ...
public class Global : System.Web.HttpApplication {
    // ...
    protected void Session_Start(Object sender, EventArgs e) {
        // ...
        WebApplication.Instance.CreateCustomLogonWindowObjectSpace +=
        application_CreateCustomLogonWindowObjectSpace;
        WebApplication.Instance.Setup();
        // ...
    }
    private static void application_CreateCustomLogonWindowObjectSpace(object sender,
    CreateCustomLogonWindowObjectSpaceEventArgs e) {
        e.ObjectSpace = ((XafApplication)sender).CreateObjectSpace(typeof(CustomLogonParameters));
        if (e.ObjectSpace is NonPersistentObjectSpace) {
            IObjectSpace objectSpaceCompany = ((XafApplication)sender).CreateObjectSpace(typeof(Company));
            ((NonPersistentObjectSpace)e.ObjectSpace).AdditionalObjectSpaces.Add(objectSpaceCompany);
        }
    }
}

修改WebApplication.cs文件

using System;
using System.Collections.Generic;
using CustomLogonParametersExample.Module;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.DC;
using DevExpress.ExpressApp.Xpo;
using DevExpress.ExpressApp.Web;
// ...
public partial class CustomLogonParametersExampleAspNetApplication : WebApplication {
    private static NonPersistentTypeInfoSource nonPersistentTypeInfoSource;
    // ...
    protected override void CreateDefaultObjectSpaceProvider(CreateCustomObjectSpaceProviderEventArgs args) {
        args.ObjectSpaceProvider =
        new XPObjectSpaceProvider(GetDataStoreProvider(args.ConnectionString, args.Connection), true);
        if (nonPersistentTypeInfoSource == null) {
            nonPersistentTypeInfoSource = new NonPersistentTypeInfoSource(TypesInfo, new List<Type>()
               { typeof(CustomLogonParameters) });
        }
        args.ObjectSpaceProviders.Add(new NonPersistentObjectSpaceProvider(TypesInfo,
        nonPersistentTypeInfoSource));
    }
}

7、到此为止项目已经可以正常启动为了方便使用修改.Module项目下的DatabaseUpdate文件夹内的Updater.cs实现内置一些数据

 在UpdateDatabaseAfterUpdateSchema方法内的 base.UpdateDatabaseAfterUpdateSchema();后追加

   PermissionPolicyRole administrativeRole = ObjectSpace.FindObject<PermissionPolicyRole>(
          new BinaryOperator("Name", SecurityStrategy.AdministratorRoleName));
            if (administrativeRole == null)
            {
                administrativeRole = ObjectSpace.CreateObject<PermissionPolicyRole>();
                administrativeRole.Name = SecurityStrategy.AdministratorRoleName;
                administrativeRole.IsAdministrative = true;
            }
            const string adminName = "Administrator";
            Employee administratorUser = ObjectSpace.FindObject<Employee>(
                new BinaryOperator("UserName", adminName));
            if (administratorUser == null)
            {
                administratorUser = ObjectSpace.CreateObject<Employee>();
                administratorUser.UserName = adminName;
                administratorUser.IsActive = true;
                administratorUser.SetPassword("");
                administratorUser.Roles.Add(administrativeRole);
            }
            PermissionPolicyRole userRole = ObjectSpace.FindObject<PermissionPolicyRole>(
                new BinaryOperator("Name", "User"));
            if (userRole == null)
            {
                userRole = ObjectSpace.CreateObject<PermissionPolicyRole>();
                userRole.Name = "User";
                userRole.AddTypePermission<Employee>(
                    SecurityOperations.ReadOnlyAccess, SecurityPermissionState.Allow);
                userRole.AddTypePermission<Company>(
                    SecurityOperations.ReadOnlyAccess, SecurityPermissionState.Allow);
            }
            if (ObjectSpace.FindObject<Company>(null) == null)
            {
                Company company1 = ObjectSpace.CreateObject<Company>();
                company1.Name = "Company 1";
                company1.Employees.Add(administratorUser);
                 }
            ObjectSpace.CommitChanges();

8、启动项目查看界面

 

 9、发现问题:如何关闭“下拉时选择公司或员工的New按钮”

 

打开Win项目下的Model.xaml文件按步骤修改

员工(Employee)和公司(Company)的LookupListView视图的AllowNew属性为Fals

问题解决 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值