前言
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 框架比較優秀,很多方面也算是最佳實踐,推薦使用。
改動比較小,修改起來也比較方便;當然也可以完全重寫 注冊的方法。下次有時間可以再整理下通過手機號登陸的實現。