一 Abp.Zero 手機號免密登錄驗證與號碼綁定功能的實現:驗證碼模塊( 二 )

public class SmsCaptchaManager : DomainService, ICaptchaManager{private readonly ISmsService SmsService;private readonly UserManager _userManager;private readonly SmsCaptchaTokenCache captchaTokenCache;public static TimeSpan TokenCacheDuration = TimeSpan.FromMinutes(5);public SmsCaptchaManager(ISmsService SmsService,UserManager userManager,SmsCaptchaTokenCache captchaTokenCache){this.SmsService=SmsService;_userManager=userManager;this.captchaTokenCache=captchaTokenCache;}}新建SendCaptchaAsync方法,作為短信發送和緩存Token方法,CommonHelp中的GetRandomCaptchaNumber()用于生成隨機6位驗證碼 , 發送完畢后,將此驗證碼作為緩存條目的Key值存入
public async Task SendCaptchaAsync(long userId, string phoneNumber, string purpose){var captcha = CommonHelper.GetRandomCaptchaNumber();var model = new SendSmsRequest();model.PhoneNumbers= phoneNumber;model.SignName="MatoApp";model.TemplateCode= purpose switch{CaptchaPurpose.BIND_PHONENUMBER => "SMS_255330989",CaptchaPurpose.UNBIND_PHONENUMBER => "SMS_255330923",CaptchaPurpose.LOGIN => "SMS_255330901",CaptchaPurpose.IDENTITY_VERIFICATION => "SMS_255330974"};model.TemplateParam= JsonConvert.SerializeObject(new { code = captcha });var result = await SmsService.SendSmsAsync(model);if (string.IsNullOrEmpty(result.BizId) && result.Code!="OK"){throw new UserFriendlyException("驗證碼發送失敗,錯誤信息:"+result.Message);}await captchaTokenCache.SetAsync(captcha, new SmsCaptchaTokenCacheItem(){PhoneNumber=phoneNumber,UserId=userId,Purpose=purpose}, absoluteExpireTime: DateTimeOffset.Now.Add(TokenCacheDuration));}綁定手機號功能實現
public async Task BindAsync(string token){SmsCaptchaTokenCacheItem currentItem = await GetToken(token);if (currentItem==null || currentItem.Purpose!=CaptchaPurpose.BIND_PHONENUMBER){throw new UserFriendlyException("驗證碼不正確或已過期");}var user = await _userManager.GetUserByIdAsync(currentItem.UserId);if (user.IsPhoneNumberConfirmed){throw new UserFriendlyException("已綁定手機,請先解綁后再綁定");}user.PhoneNumber=currentItem.PhoneNumber;user.IsPhoneNumberConfirmed=true;await _userManager.UpdateAsync(user);await RemoveToken(token);}解綁手機號功能實現
public async Task UnbindAsync(string token){SmsCaptchaTokenCacheItem currentItem = await GetToken(token);if (currentItem==null|| currentItem.Purpose!=CaptchaPurpose.UNBIND_PHONENUMBER){throw new UserFriendlyException("驗證碼不正確或已過期");}var user = await _userManager.GetUserByIdAsync(currentItem.UserId);user.IsPhoneNumberConfirmed=false;await _userManager.UpdateAsync(user);await RemoveToken(token);}驗證功能實現
public async Task<bool> VerifyCaptchaAsync(string token, string purpose = CaptchaPurpose.IDENTITY_VERIFICATION){SmsCaptchaTokenCacheItem currentItem = await GetToken(token);if (currentItem==null || currentItem.Purpose!=purpose){return false;}await RemoveToken(token);return true;}實際業務中可能還需要Email驗證,我也建立了電子郵箱驗證碼的領域服務類,只不過沒有實現它 , 動手能力強的讀者可以試著完善這個小案例:)

一 Abp.Zero 手機號免密登錄驗證與號碼綁定功能的實現:驗證碼模塊

文章插圖
Api實現AppService層創建CaptchaAppService.cs,并寫好接口
public class CaptchaAppService : ApplicationService{private readonly SmsCaptchaManager captchaManager;public CaptchaAppService(SmsCaptchaManager captchaManager){this.captchaManager=captchaManager;}[HttpPost]public async Task SendAsync(SendCaptchaInput input){await captchaManager.SendCaptchaAsync(input.UserId, input.PhoneNumber, input.Type);}[HttpPost]public async Task VerifyAsync(VerifyCaptchaInput input){await captchaManager.VerifyCaptchaAsync(input.Token);}[HttpPost]public async Task UnbindAsync(VerifyCaptchaInput input){await captchaManager.UnbindAsync(input.Token);}[HttpPost]public async Task BindAsync(VerifyCaptchaInput input){await captchaManager.BindAsync(input.Token);}}
一 Abp.Zero 手機號免密登錄驗證與號碼綁定功能的實現:驗證碼模塊

文章插圖
至此我們就完成了驗證碼相關邏輯的接口下一章將介紹如何重寫Abp默認方法,以集成手機號登錄功能 。
注意!不要將本示例作為生產級代碼使用本示例中,驗證碼校驗的接口并沒有做嚴格加密 , 6位驗證碼也很容易被破解,因此需要考慮這些安全問題 。在實際生產代碼中 , 驗證的參數常用手機號+驗證碼做哈希運算保證安全 。
項目地址Github:matoapp-samples
【一 Abp.Zero 手機號免密登錄驗證與號碼綁定功能的實現:驗證碼模塊】

推薦閱讀