Abp 實現通過手機號註冊使用者

高堂古秋發表於2022-04-11

前言

Abp 的 Identity 模組,實現了使用者的管理,但是對於國內來講,很多場景不能很好適配。比如:通過手機號進行註冊的場景。

Abp vnext Identity 以及 asp.net core identity  預設只有 Email 必填以及唯一的校驗,缺少手機號必要的校驗;對此我們需要進行適當的調整,以作適配。

 

準備

 

建議先參考 IdentityUserAppService 對使用者註冊的實現;

由於手機號驗證的場景基本上是需要的,所以本次採用重寫的方式,當然也可以參考其程式碼,自定義自己的實現。

 

Application 

 public class PublicAccountAppService: IdentityUserAppService
    {
        public PublicAccountAppService(
            IdentityUserManager userManager,
            IIdentityUserRepository userRepository,
            IIdentityRoleRepository roleRepository,
            IOptions<IdentityOptions> identityOptions) 
            : base(userManager, userRepository, roleRepository, identityOptions)
        {

        }

        public override async Task<IdentityUserDto> CreateAsync(
            IdentityUserCreateDto input)
        {
            ValidateRegisterInput(input);
            await CheckRegisterableByPhone(input.PhoneNumber);
            return await base.CreateAsync(input);
        }

        private static void ValidateRegisterInput(IdentityUserCreateDto input)
        {
            if (input.PhoneNumber.IsNullOrWhiteSpace())
            {
                throw new AbpValidationException(
                    "Phone number is required for new users!",
                    new List<ValidationResult>
                    {
                        new ValidationResult(
                            "Phone number can not be empty!",
                            new []{"PhoneNumber"}
                        )
                    }
                );
            }
        }

        private async Task CheckRegisterableByPhone(string phoneNumber)
        {
            var isPhoneNumberExist = await _accountRepository.IsPhoneNumberExistAsync(phoneNumber);
            if (isPhoneNumberExist)
            {
                throw new AbpValidationException(
                    "Phone number already exist!",
                    new List<ValidationResult>
                    {
                        new ValidationResult(
                            "Phone number already exist!",
                            new []{"PhoneNumber"}
                        )
                    }
                );
            }
        }
    }

  

Domain

由於 IIdentityUserRepository 缺少對手機號是否存在的預設實現,我們可以新增對應Repository 來實現相關功能。

儘量遵守DDD 分層的原則。

Abp 實現通過手機號註冊使用者
1  public interface IAccountRepository
2     {
3         Task<bool> IsPhoneNumberExistAsync(string phoneNumber);
4     }
View Code

 

Repository

實現Domain 層定義的介面

Abp 實現通過手機號註冊使用者
 1  public class AccountRepository: IAccountRepository, ITransientDependency
 2     {
 3         private readonly IRepository<IdentityUser, Guid> _identityUserRepository;
 4 
 5         public AccountRepository(IRepository<IdentityUser, Guid> identityUserRepository)
 6         {
 7             _identityUserRepository = identityUserRepository;
 8         }
 9 
10         public async Task<bool> IsPhoneNumberExistAsync(string phoneNumber)
11         {
12             return await _identityUserRepository.AnyAsync(
13                 c => c.PhoneNumber == phoneNumber);
14         }
15     }
View Code

 

替換預設例項

我們已經完成了對 IdentityUserAppService 建立方法的重寫,需要替換預設的介面例項物件,可以參考 Customizing Application Modules Overriding Services | Documentation Center | ABP.IO

Abp 實現通過手機號註冊使用者
    [Dependency(ReplaceServices = true)]
    [ExposeServices(typeof(IIdentityUserAppService), typeof(IdentityUserAppService), typeof(PublicAccountAppService))]
    public class PublicAccountAppService: IdentityUserAppService
    {...}
View Code

 

其他

主要的修改已經調整完畢。但是由於AbpUser 表沒有 PhoneNumber 的相關索引,可以自行通過 Migration 進行新增。

Abp 框架比較優秀,很多方面也算是最佳實踐,推薦使用。

改動比較小,修改起來也比較方便;當然也可以完全重寫 註冊的方法。下次有時間可以再整理下通過手機號登陸的實現。

 

相關文章