zoukankan      html  css  js  c++  java
  • Module Zero之用户管理

    返回《Module Zero学习目录》


    用户实体##

    用户实体代表应用的一个用户,它派生自AbpUser类,如下所示:

    public class User : AbpUser<Tenant, User>
    {
        //这里添加你自己的用户属性
    }
    
    

    这个类是你在安装module-zero时自动创建的。用户数据存储在数据库中的AbpUsers表。你可以添加User类的自定义属性(以及针对改变创建数据库迁移)。
    AbpUser类定义的基本属性如下:

    • UserName:用户的登录名,对于一个租户来说应该是唯一的。
    • EmailAddress:用户的邮箱地址。对于租户来说应该是唯一的。
    • Password:用户的哈希密码。
    • IsActive:如果用户可以登录到该应用,那么此值为true。
    • NameSurname:用户的名和姓。

    还有许多属性,如Roles, Permissions, Tenant, Settings, IsEmailConfirmed等等。你可以在AbpUser类中查看更多信息。

    AbpUser类派生自FullAuditedEntity。这意味着它有创建,修改和删除的审计属性。它也支持软删除。因此当我们删除一个用户的时候,实际上它并没有从数据库中删除,而是仅仅标记为已删除的状态。

    为了在一个多租户的应用中更好地工作,AbpUser类实现了IMayHaveTenant过滤器。
    最后,User的Id定义为long类型。

    用户管理者##

    用户管理者是执行用户领域逻辑的服务:

    public class UserManager : AbpUserManager<Tenant, Role, User>
    {
        //...
    }
    
    

    你可以注入用户管理者,然后使用它来创建,删除,更新用户,为用户授权,改变角色以及更多。你可以在这里添加你自己的方法。而且,你可以重写AbpUserManager基类的任何方法来满足你自己的需求。

    多租户

    如果你创建的不是一个多租户应用,那么你可以跳过本节。

    曾经设计UserManager的目的是为单租户服务的。默认是为当前租户服务的。接下来看一下UserManager的一些用法:

    public class MyTestAppService : ApplicationService
    {
        private readonly UserManager _userManager;
    
        public MyTestAppService(UserManager userManager)
        {
            _userManager = userManager;
        }
    
        public void TestMethod_1()
        {
            //Find a user by email for current tenant
            var user = _userManager.FindByEmail("sampleuser@aspnetboilerplate.com");
        }
    
        public void TestMethod_2()
        {
            //Switch to tenant 42
            CurrentUnitOfWork.SetFilterParameter(AbpDataFilters.MayHaveTenant, AbpDataFilters.Parameters.TenantId, 42);
    
            //Find a user by email for the tenant 42
            var user = _userManager.FindByEmail("sampleuser@aspnetboilerplate.com");
        }
    
        public void TestMethod_3()
        {
            //Disabling MayHaveTenant filter, so we can reach to all users
            using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.MayHaveTenant))
            {
                //Now, we can search for a user name in all tenants
                var users = _userManager.Users.Where(u => u.UserName == "sampleuser").ToList();
    
                //Or we can add TenantId filter if we want to search for a specific tenant
                var user = _userManager.Users.FirstOrDefault(u => u.TenantId == 42 && u.UserName == "sampleuser");
            }
        }
    }
    
    

    用户登录

    UserManager有一个登录到该应用的LoginAsync方法。它检查所有的登录逻辑并返回一个登录结果。查看样例AccountController中Login方法的示例用法。

    关于IdentityResults

    UserManager的一些方法返回了IdentityResult作为结果而不是抛出一些情况的异常。这是ASP.NET Identity Framework的本质。Module-zero也遵循这个。因此,我们可以查看这个返回的结果对象就可知道操作是否成功。

    Module-zero定义了CheckErrors扩展方法,它可以自动地检查错误,如果需要,也会抛出异常(本地化的UserFriendlyException)。样例用法:

    (await UserManager.CreateAsync(user)).CheckErrors();
    

    为了获得一个本地化的异常,我们应该提供一个ILocalizationManager实例:

    (await UserManager.CreateAsync(user)).CheckErrors(LocalizationManager);
    

    外部认证

    Module-zero的Login方法会认证数据库的AbpUsers表中的用户。一些应用可能要求认证来自外部资源的用户(比如活动目录,来自其他数据库的表,甚至来自一个远程服务)。

    对于很多情况,UserManager定义了一个名叫“外部认证资源”的扩展点。我们可以创建一个派生自**IExternalAuthenticationSource 的类,然后将它注册到配置中。有一个简化了IExternalAuthenticationSource的实现的类DefaultExternalAuthenticationSource **,来看一个例子:

    public class MyExternalAuthSource : DefaultExternalAuthenticationSource<Tenant, User>
    {
        public override string Name
        {
            get { return "MyCustomSource"; }
        }
    
        public override Task<bool> TryAuthenticateAsync(string userNameOrEmailAddress, string plainPassword, Tenant tenant)
        {
            //TODO: authenticate user and return true or false
        }
    }
    
    

    在TryAuthenticateAsync方法中,我们可以检查来自某些资源的用户名和密码,如果给定的用户通过了该资源的认证,那么返回true。而且,我们可以重写CreateUser和UpdateUser方法来控制该资源的用户创建和更新。

    当外部资源验证通过一个用户后,module-zero会检查数据库(AbpUser表)中是否存在该用户。如果不存在,就会调用CreateUser来创建该用户,否则调用UpdateUser使外部源更新已存在的用户信息。

    在一个应用中,我们可以定义不止一个外部源。AbpUser实体有一个AuthenticationSource属性,它表明了哪个源认证了该用户。

    为了注册认证源,我们可以在模块中的PreInitialize方法使用这些代码:

    Configuration.Modules.Zero().UserManagement.ExternalAuthenticationSources.Add<MyExternalAuthSource>();
    

    LDAP/活动目录

    LdapAuthenticationSource是一个外部认证的实现,它可以让用户使用他们的LDAP(活动目录)用户名和密码登录。

    如果我们想要使用LDAP认证,那么我们首先要将Abp.Zero.Ldap添加到项目中(通常添加到Core(领域)项目)。然后,我们应该给应用扩展LdapAuthenticationSource,如下所示:

    public class MyLdapAuthenticationSource : LdapAuthenticationSource<Tenant, User>
    {
        public MyLdapAuthenticationSource(ILdapSettings settings, IAbpZeroLdapModuleConfig ldapModuleConfig)
            : base(settings, ldapModuleConfig)
        {
        }
    }
    
    

    最后,我们应该设置AbpZeroLdapModule的模块依赖,然后开启上面创建的LDAP认证源:

    [DependsOn(typeof(AbpZeroLdapModule))]
    public class MyApplicationCoreModule : AbpModule
    {
        public override void PreInitialize()
        {
            Configuration.Modules.ZeroLdap().Enable(typeof (MyLdapAuthenticationSource));
        }
    
        ...
    }
    
    

    这些步骤之后,你的应用就开启了LDAP模块。但LDAP认证默认没有开启,我们可以使用设置来开启它。

    设置

    LdapSettingNames类定义了一些设置名称的常量。当要改变设置(或者获取设置)时,你可以使用这些常量名称。LDAP设置是每个租户的(对于多租户应用)。因此,不同的租户有不同的设置。(在github上查看设置的定义)

    正如你在MyLdapAuthenticationSource的构造函数中看到的,LdapAuthenticationSource期望ILdapSettings作为构造函数参数。该接口用于获得LDAP设置,如领域,用户名和密码,以连接到活动目录。默认的实现(LdapSetting类)从设置管理者中获得这些设置。

    如果你使用了设置管理者,你可以使用设置管理者的API改变LDAP的设置。如果你想要的话,你可以通过将一个初始化/种子数据添加到数据库来默认开启LDAP认证。

    注意:如果你没有定义领域,用户名和密码,且你的应用运行在具有合适权限的领域中,那么LDAP认证只对当前的领域有效。

    自定义设置

    如果你想定义其他的设置源,那么你可以实现一个自定义的ILdapSettings类,如下所示:

    public class MyLdapSettings : ILdapSettings
    {
        public async Task<bool> GetIsEnabled(int? tenantId)
        {
            return true;
        }
    
        public async Task<ContextType> GetContextType(int? tenantId)
        {
            return ContextType.Domain;
        }
    
        public async Task<string> GetContainer(int? tenantId)
        {
            return null;
        }
    
        public async Task<string> GetDomain(int? tenantId)
        {
            return null;
        }
    
        public async Task<string> GetUserName(int? tenantId)
        {
            return null;
        }
    
        public async Task<string> GetPassword(int? tenantId)
        {
            return null;
        }
    }
    
    

    然后在模块中的PreInitialize方法里将它注册到IOC中:

    [DependsOn(typeof(AbpZeroLdapModule))]   
    public class MyApplicationCoreModule : AbpModule
    {
        public override void PreInitialize()
        {
            IocManager.Register<ILdapSettings, MyLdapSettings>(); //change default setting source
            Configuration.Modules.ZeroLdap().Enable(typeof (MyLdapAuthenticationSource));
        }
    
        ...
    }
    
    

    这样,你就可以从其他资源获得LDAP设置了。

  • 相关阅读:
    C++中使用多线程
    hdu 4223 dp 求连续子序列的和的绝对值最小值
    hdu 1372 bfs 计算起点到终点的距离
    hdu 4217 线段树 依次取第几个最小值,求其sum
    心得
    hdu 1175 bfs 按要求进行搜索,是否能到达,抵消两个(相同)棋子
    hdu 4221 greed 注意范围 工作延期,使整个工作时间罚时最少的单个罚时最长的值
    hdu 2844 多重背包 多种硬币,每一种硬币有一点数量,看他能组成多少种钱
    uva LCDDisplay
    hdu 4218 模拟 根据一个圆点和半径画一个圆 注意半径要求
  • 原文地址:https://www.cnblogs.com/farb/p/moduleZeroUserManagement.html
Copyright © 2011-2022 走看看