这是一篇系列博文 , 我将使用Abp.Zero搭建一套集成手机号免密登录验证与号码绑定功能的用户系统:
- Abp.Zero 手机号免密登录验证与号码绑定功能的实现(一):验证码模块
- Abp.Zero 手机号免密登录验证与号码绑定功能的实现(二):改造Abp默认实现
- Abp.Zero 手机号免密登录验证与号码绑定功能的实现(三):网页端开发
首先来厘清这两个不同的业务在Abp中的实现,我之前写的这篇 Abp.Zero 搭建第三方登录模块 系列文章中描述的业务,即使用的Abp外部身份授权(ExternalAuth)的相关扩展而实现的 。还记得我们实现的WeChatAuthProvider吗?它继承于ExternalAuthProviderApi这个抽象类,实现的微信授权功能 。所以微信登录这个动作,实际是在授权(Authorization)已有的微信账号,访问服务端资源,而身份验证(Authentication)步骤,已在其他端完成了(手机微信扫码) , 在服务端获取已验证好身份的第三方账户并生成Token则可以抽象的认为是授权(Authorization)行为 。
所以“搭建第三方登录模块”应该更准确地描述为“第三方授权模块” 。
从Abp接口设计上 , 也能看得出来两者的差别 。
外部身份验证(ExternalAuthentication)关注的是校验 , 实现TryAuthenticateAsync并返回是否成功,而CreateUserAsync和UpdateUserAsync仅是校验流程里的一部分,不实现它并不影响身份验证结果 , 外部授权源的接口定义如下,
public interface IExternalAuthenticationSource<TTenant, TUser> where TTenant : AbpTenant<TUser> where TUser : AbpUserBase{...Task<bool> TryAuthenticateAsync(string userNameOrEmailAddress, string plainPassword, TTenant tenant);Task<TUser> CreateUserAsync(string userNameOrEmailAddress, TTenant tenant);Task UpdateUserAsync(TUser user, TTenant tenant);}
外部授权(ExternalAuth)这一步关注的业务是拿到外部账号,如微信的OpenId,所以IExternalAuthManager重点则是GetUserInfo,而IsValidUser并没有在默认实现中使用到public interface IExternalAuthManager{Task<bool> IsValidUser(string provider, string providerKey, string providerAccessCode);Task<ExternalAuthUserInfo> GetUserInfo(string provider, string accessCode);}
然而这些是从LoginManager原本实现看出的,我们可以重写这个类原本的方法 , 加入电话号码的处理逻辑 。在搞清楚这两个接口后,相信你会对Abp用户系统的理解更加深刻
短信获取验证码来校验,是比较常用的第三方身份验证方式,今天来做一个手机号码免密登录,并且具有绑定/解绑手机号功能的小案例,效果如图:
文章插图
示例代码已经放在了GitHub上:Github:matoapp-samples
用户验证码校验模块首先定义DomainService接口 , 我们将实现手机验证码的发送、验证码校验、解绑手机号、绑定手机号
这4个功能,并且定义用途以校验行为合法性,和用它来区分短信模板
public interface ICaptchaManager{Task BindAsync(string token);Task UnbindAsync(string token);Task SendCaptchaAsync(long userId, string phoneNumber, string purpose);Task<bool> VerifyCaptchaAsync(string token, string purpose = "IDENTITY_VERIFICATION");}
public const string LOGIN = "LOGIN";public const string IDENTITY_VERIFICATION = "IDENTITY_VERIFICATION";public const string BIND_PHONENUMBER = "BIND_PHONENUMBER";public const string UNBIND_PHONENUMBER = "UNBIND_PHONENUMBER";
定义一个验证码Token缓存管理类,以及对应的缓存条目类,用于承载验证码的校验内容public class SmsCaptchaTokenCache : MemoryCacheBase<SmsCaptchaTokenCacheItem>, ISingletonDependency{public SmsCaptchaTokenCache() : base(nameof(SmsCaptchaTokenCache)){}}
缓存条目将存储电话号码 , 用户Id(非登录用途)以及用途public class SmsCaptchaTokenCacheItem{public string PhoneNumber { get; set; }public long UserId { get; set; }public string Purpose { get; set; }}
阿里云和腾讯云提供了短信服务Sms,是国内比较常见的短信服务提供商,不需要自己写了,网上有大把的封装好的库,这里使用AbpBoilerplate.Sms作为短信服务库 。创建短信验证码的领域服务类SmsCaptchaManager并实现ICaptchaManager接口,同时注入短信服务ISmsService,用户管理服务UserManager,验证码Token缓存管理服务SmsCaptchaTokenCache
推荐阅读
- 三 Java多线程-ThreadPool线程池
- c++ 模板 指针类型偏特化
- 一个实用的 vite + vue3 组件库脚手架工具,提升开发效率
- 二、.Net Core搭建Ocelot
- 用一台笔记本电脑如何赚钱(笔记本电脑赚钱的办法)
- 有哪些在家用电脑就可以赚钱的办法,一天七八十就可以了
- 一 Java多线程-线程生命周期
- 创建.NET程序Dump的几种姿势
- 一台虚拟机,基于docker搭建大数据HDP集群
- 支持JDK19虚拟线程的web框架,之二:完整开发一个支持虚拟线程的quarkus应用