前言
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 }
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 }
替換預設例項
我們已經完成了對 IdentityUserAppService 建立方法的重寫,需要替換預設的介面例項物件,可以參考 Customizing Application Modules Overriding Services | Documentation Center | ABP.IO
[Dependency(ReplaceServices = true)] [ExposeServices(typeof(IIdentityUserAppService), typeof(IdentityUserAppService), typeof(PublicAccountAppService))] public class PublicAccountAppService: IdentityUserAppService {...}
其他
主要的修改已經調整完畢。但是由於AbpUser 表沒有 PhoneNumber 的相關索引,可以自行通過 Migration 進行新增。
Abp 框架比較優秀,很多方面也算是最佳實踐,推薦使用。
改動比較小,修改起來也比較方便;當然也可以完全重寫 註冊的方法。下次有時間可以再整理下通過手機號登陸的實現。