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