­

Abp 實現通過手機號註冊用戶

前言

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 分層的原則。

1  public interface IAccountRepository
2     {
3         Task<bool> IsPhoneNumberExistAsync(string phoneNumber);
4     }

View Code

 

Repository

實現Domain 層定義的介面

 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

    [Dependency(ReplaceServices = true)]
    [ExposeServices(typeof(IIdentityUserAppService), typeof(IdentityUserAppService), typeof(PublicAccountAppService))]
    public class PublicAccountAppService: IdentityUserAppService
    {...}

View Code

 

其他

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

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

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