循序渐进VUE+Element 前端应用开发(32)--- 手机短信动态码登陆处理
在一些系统中,有时候用户忘记密码,可以通过向自己手机发送动态验证码的方式实现系统登录功能。本篇随笔介绍如何结合后端ABP框架的短信发送和缓存模块的处理,实现手机短信动态码登陆处理。
一般的登录方式,分为普通账号登录,动态密码登陆,扫描二维码登录这里不讲,主要介绍动态码登录方式。
1、短信验证码的发送处理
我在上篇随笔《ABP框架中短信发送处理,包括阿里云短信和普通短信商的短信发送集成》中介绍了如何使用ABP框架实现短信的发送处理,因此我们前后端通过短信的方式,可以实现动态密码的登陆处理。
因此在授权登陆的控制器中,我们增加短信发送的接口注入使用,如下所示。
然后通过定义两个接口,一个是发送动态验证码给用户手机的接口,一个是根据用户手机和动态验证码的方式进行登录处理接口。
然后我们在这个验证身份的控制器上增加两个方法即可。
用例也就是分了两个处理方法。
在处理发送短信验证码之前,我们来介绍一下短信验证码的处理规则,我们发送短信成功后,把验证码存在系统缓存里面,一般系统缓存是存放在Redis里面,缓存需要一个键和定义好的类对象进行存储。
我们定义好存储的对象类,再在系统中使用即可。
/// <summary>
/// 短信登陆动态密码缓存对象
/// </summary>
[Serializable]
public class SmsLoginCodeCacheItem
{
public const string CacheName = "AppSmsLoginCodeCacheItem"; public string Code { get; set; } public string PhoneNumber { get; set; } public SmsLoginCodeCacheItem()
{
} public SmsLoginCodeCacheItem(string code, string phone)
{
Code = code;
PhoneNumber = phone;
}
}
我们可以在系统模块初始化的时候,配置好缓存对应的失效时间,如下所示。
//配置SMS登录动态码有效期限
Configuration.Caching.Configure(SmsLoginCodeCacheItem.CacheName, cache =>
{
cache.DefaultSlidingExpireTime = TimeSpan.FromMinutes(Constants.SmsCodeExpiredMinutes);
});
发送短信验证码作为动态密码的逻辑代码如下所示。
/// <summary>
/// 发送登录动态码
/// </summary>
/// <param name="model">手机登录动态码</param>
/// <returns></returns>
[HttpPost]
public async Task<CommonResult> SendPhoneLoginSmsCode([FromBody] AuthenticateByPhoneCaptchaModel model)
{
//获取随机6位数字动态验证码
var code = RandomHelper.GetRandom(100000, 999999).ToString(); //使用自定义模板处理短信发送
string message = string.Format(Constants.MySmsCodeTemplate, code);
var result = await _smsSender.SendAsync(model.PhoneNumber, message);
if(result.Success)
{
var cacheKey = model.PhoneNumber;//以手机号码作为键存储验证码缓存
var cacheItem = new SmsLoginCodeCacheItem { Code = code, PhoneNumber = model.PhoneNumber }; var cache = _cacheManager.GetCache<string, SmsLoginCodeCacheItem>(SmsLoginCodeCacheItem.CacheName);
cache.Set(cacheKey, cacheItem);
} return result;
}
我们还需要在前端中设计一个使用动态短信码登录的界面,如下所示。
短信发送成功,可以在用户手机查看对应的动态码。
验证码发送后,我们也可以在Redis中看到对应的数据,如下所示。
2、动态码登录处理
发送了短信码后,系统在缓存中存放一段时间的数据,如果在这个期间进行登录,会根据缓存进行匹配,如果匹配成功,那么就进行相关登录身份的处理即可。
系统登录验证的处理代码如下所示。
/// <summary>
/// 通过手机验证码授权
/// </summary>
/// <param name="model">手机验证码Dto</param>
/// <returns></returns>
[HttpPost]
public async Task<AuthenticateResultModel> AuthenticateByPhoneCaptcha([FromBody] AuthenticateByPhoneCaptchaModel model)
{
var loginResult = await GetLoginResultByPhoneCaptchaAsync(
model.PhoneNumber,
model.SmsCode,
GetTenancyNameOrNull()
); //if(loginResult.Result == AbpLoginResultType.Success)
//这里成功,移除短信缓存
var cache = _cacheManager.GetCache<string, SmsLoginCodeCacheItem>(SmsLoginCodeCacheItem.CacheName);
cache.Remove(model.PhoneNumber);//移除缓存短信键值 var accessToken = CreateAccessToken(CreateJwtClaims(loginResult.Identity));
return new AuthenticateResultModel
{
AccessToken = accessToken,
ExpireInSeconds = (int)_configuration.Expiration.TotalSeconds,
EncryptedAccessToken = GetEncryptedAccessToken(accessToken),
UserId = loginResult.User.Id
};
}
这里主要的逻辑封装在 GetLoginResultByPhoneCaptchaAsync 中,这个登录的方式可以参考ABP框架基础的登陆方式进行改动即可。
/// <summary>
/// 获取登陆结果通过手机验证码
/// </summary>
/// <param name="phoneNumber">手机号</param>
/// <param name="captcha">验证码</param>
/// <param name="tenancyName">租户名</param>
/// <returns></returns>
private async Task<AbpLoginResult<Tenant, User>> GetLoginResultByPhoneCaptchaAsync(string phoneNumber, string captcha, string tenancyName)
{
var loginResult = await _logInManager.LoginByMobileAsync(phoneNumber, captcha, tenancyName);
switch (loginResult.Result)
{
case AbpLoginResultType.Success:
return loginResult;
default:
throw _abpLoginResultTypeHelper.CreateExceptionForFailedLoginAttempt(loginResult.Result, loginResult.User.UserName, tenancyName);
}
}
参照ABP框架基础的登陆授权方式,我们在UserManager中增加类似的验证码登陆管理方式,如下所示。
前端在处理相关发送验证码和登录授权的操作,是针对API的调用,因此需要封装对应的API处理。
然后仿照常规登录的处理,编写一个动态码登录的处理方式,放在对应的Module中即可。
dynamiclogin({ commit }, userInfo) { // 动态密码登陆
const { mobile, smscode } = userInfo
return new Promise((resolve, reject) => {
tokenauth.AuthenticateByPhoneCaptcha({ phoneNumber: mobile.trim(), smsCode: smscode }).then(response => {
const { result } = response // 获取返回对象的 result
// console.log(result)// 记录数据
var token = result.accessToken // 用户令牌
var userId = result.userId // 用户id // 修改State对象,记录令牌和用户Id
commit('SET_TOKEN', token)
commit('SET_USERID', userId)
// 存储cookie
setToken(token)
setUserId(userId) resolve()
}).catch(error => {
reject(error)
})
})
},
在登录界面中,输入动态码登录即可顺利进入系统,和常规的处理一样。
以上就是参照常规账号密码登录的方式,构建一个动态码登录的处理,流程还是差不多,不过整合了短信发送,缓存处理,账号登陆等几个流程,可以作为一个简单的系统登录过程的了解。
循序渐进VUE+Element 前端应用开发(32)--- 手机短信动态码登陆处理的更多相关文章
- 循序渐进VUE+Element 前端应用开发(26)--- 各种界面组件的使用(2)
在我们使用Vue+Element开发前端的时候,往往涉及到很多界面组件的使用,其中很多直接采用Element官方的案例即可,有些则是在这个基础上封装更好利用.更少代码的组件:另外有些则是直接采用第三方 ...
- 循序渐进VUE+Element 前端应用开发(4)--- 获取后端数据及产品信息页面的处理
在前面随笔<循序渐进VUE+Element 前端应用开发(3)--- 动态菜单和路由的关联处理>中介绍了在Vue + Element整合框架中,实现了动态菜单和动态路由的处理,从而可以根据 ...
- 循序渐进VUE+Element 前端应用开发(5)--- 表格列表页面的查询,列表展示和字段转义处理
在我们一般开发的系统界面里面,列表页面是一个非常重要的综合展示界面,包括有条件查询.列表展示和分页处理,以及对每项列表内容可能进行的转义处理,本篇随笔介绍基于Vue +Element基础上实现表格列表 ...
- 循序渐进VUE+Element 前端应用开发(6)--- 常规Element 界面组件的使用
在我们开发BS页面的时候,往往需要了解常规界面组件的使用,小到最普通的单文本输入框.多文本框.下拉列表,以及按钮.图片展示.弹出对话框.表单处理.条码二维码等等,本篇随笔基于普通表格业务的展示录入的场 ...
- 循序渐进VUE+Element 前端应用开发(8)--- 树列表组件的使用
在我前面随笔<循序渐进VUE+Element 前端应用开发(6)--- 常规Element 界面组件的使用>里面曾经介绍过一些常规的界面组件的处理,主要介绍到单文本输入框.多文本框.下拉列 ...
- 循序渐进VUE+Element 前端应用开发(9)--- 界面语言国际化的处理
我们开发的系统,一般可以不用考虑语言国际化的问题,大多数系统一般是给本国人使用的,而且直接使用中文开发界面会更加迅速 一些,不过框架最好能够支持国际化的处理,以便在需要的时候,可以花点时间来实现多语言 ...
- 循序渐进VUE+Element 前端应用开发(10)--- 基于vue-echarts处理各种图表展示
在我们做应用系统的时候,往往都会涉及图表的展示,综合的图表展示能够给客户带来视觉的享受和数据直观体验,同时也是增强客户认同感的举措之一.基于图表的处理,我们一般往往都是利用对应第三方的图表组件,然后在 ...
- 循序渐进VUE+Element 前端应用开发(12)--- 整合ABP框架的前端登录处理
VUE+Element 前端是一个纯粹的前端处理,前面介绍了很多都是Vue+Element开发的基础,从本章随笔开始,就需要进入深水区了,需要结合ABP框架使用(如果不知道,请自行补习一下我的随笔:A ...
- 循序渐进VUE+Element 前端应用开发(13)--- 前端API接口的封装处理
在前面随笔<循序渐进VUE+Element 前端应用开发(12)--- 整合ABP框架的前端登录处理>介绍了一个系统最初接触到的前端登录处理的实现,但往往对整个系统来说,一般会有很多业务对 ...
随机推荐
- 第九章 Python文件操作
前一阵子写类相关的内容,把老猿写得心都累了,本来准备继续介绍一些类相关的知识的,如闭包.装饰器.描述符.枚举类.异常等,现在实在不想继续,以后再开章节吧.本章弄点开胃的小菜提提神,介绍Python中文 ...
- PyQt(Python+Qt)学习随笔:model/view架构中支持QListView列表中展示图标的两种方法
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 在QListView列表视图中的项不但可以展示文字,也可以展示图标和复选框,同时可以指定项是否可以拖 ...
- 科大讯飞语音合成系统 V5.0绿色便携版
中文名: 中科大讯飞Interphonic 5.0语音合成系统英文名: Interphonic 5.0版本: 5.0发行时间: 2006年制作发行: 中科大讯飞语言: 简体中文系统简介InterPho ...
- 第 2 篇 Scrum 冲刺博客
一.站立式会议 1.站立式会议照片 2.昨天已完成的工作 ①大部分同学成功用java连接数据库 ②前端和后台的成员成功讨论并了解具体需求 3.今天计划完成的工作 ①帮助不会的同学连接数据库 ②登录识别 ...
- es6 Object对象扩展新方法
ES6给Object拓展了许多新的方法,如: keys(obj):获取对象的所有key形成的数组 var obj = { foo: 'bar', baz: 42 }; Object.keys ...
- Win10 .net framework 3.5 安装失败 0x80073712 [解决了]
Win10 .net framework 3.5 安装失败 0x80073712 用了各种办法,一直解决不了. 最后用了: 使用 https://www.microsoft.com/zh-cn/sof ...
- 学习笔记:舞蹈链 Dancing Links
这是一种奇妙的算法用来解决两个问题: 精确覆盖问题:给定一个矩阵,每行是一个二进制数,选出尽量少的行,使得每一列恰好有一个 \(1\) 重复覆盖问题:给定一个矩阵,每行是一个二进制数,选出尽量少的行, ...
- AcWing 1194. 岛和桥
\(f[s][i][j]\) 表示一条有向路径(不经过重复点),当前路径点集合为 \(s\),最后两个点是 \(j\) → \(i\) 的最大价值 \(g[s][i][j]\) 类似,不过是方案数. ...
- 题解-Enemy is weak
Enemy is weak 求序列 \(a\{n\}\) 中的三元逆序对数量. 数据范围:\(3\le n\le 1e6\). 这题真是一道又好又水的题,可是我看别人的题解做法真是玄学难懂,于是蒟蒻要 ...
- Int,String,Integer,double之间的类型的相互转换
Int整数,String字符串之间的类型的转换 int转成String 结果为: String转成int类型 结果为: double转成String 结果为: String转成double 结果为: ...