前言
短信验证登录 / 注册是目前很主流的一种登录模式,对于小型企业或者个人开发者而言,这种登录方式可以足够自然地拿到用户的电话号码,也能确保操作者就是用户本人,有一定的安全保障。
在我的毕设中,我设计的用客户端登录方式就是短信验证码登录。这篇文章会着重讲一下作为个人开发者(无企业资质),是如何完成短信验证码登录的。
技术选项:Node.js(Koa2)、Mysql、阿里云短信服务
实现过程
做功能之前先搞清楚需求。我的小项目中,登录这方面的需求就是:短信验证码登录,没有登录过的用户自动完成注册并且登录。它整个的业务逻辑并不复杂,大体模块可以分为这两个:发送验证码 + 验证并且登录。
发送验证码
演示效果
先看看演示效果。发送验证码应该是一个单独的接口。这里的业务逻辑是 接收使用户手机号 -> 生成随机数 -> 将随机数和手机号存入临时表单 -> 请求阿里云短信服务向用户发送验证码。
//生成随机数
const randomCode = function () {
var str = "0123456789";
var result2 = "";
for (var i = 6; i > 0; --i)
result2 += str[Math.floor(Math.random() * str.length)];
return result2;
};
生成随机数之后,相对于的是要将用户的手机号码和验证码存入临时表单以待验证。这里涉及到技术选型的问题,一般来说处理这些缓存类的数据主流用的是Redis,它可以设置缓存的有效期,也可以减少数据库的读写压力。但因为是个人的小项目,这里我只用Mysql实现。
存入临时表单
login_code表设计
login_code的这个表很简单,只有phone和code两个字段。这里涉及到一个验证码有效时长的问题,当然了,Mysql也是支持定时事件线程的(如果需要,可以看看mysql相关的文章),但是这里我想让服务器定时删除就好。
验证码存入流程
//代码过长,这里贴出sql指令供理解
let isSend = `select * from login_code where phone = ${myphone}`,
if (isSend) {
`update login_code set code= ${codemsg} where phone = ${myphone}`
} else {
`INSERT INTO login_code (phone,code) values(${myphone},${codemsg})`
}
setTimeout(async () => {
`DELETE FROM login_code WHERE phone=${myphone} and code=${codemsg}`
}, 300000);
如果是正式的项目,这部分内容最好是用Redis实现。
阿里云短信服务
短信云服务必不可少。市场上有好几家云短信服务,腾讯云、阿里云、华为云... ...都是不错的选择,价格也差不太多。这里强调一下最好还是选大公司的云服务,默默吐槽一下之前作为备选的榛子云,注册他们自己网站的验证码都半天发不过来!最后我选的是阿里云,学生优惠打折的时候买很便宜,似乎是1000条1年20元。
不过,由于相关政策的完善,云短信服务的签名和模板审核变得异常严格,对个人开发者的要求是:要具有已经备案的网站或者上线的程序,且具有验证码场景的功能。由于我有已经备案的个人博客,做一个类似验证码登录的页面就可以轻松通过审核了。
网站的服务器、域名及备案我都是用的阿里云的服务,都很方便,只是需要一些时间成本。
如果你还没有已经备案的网站,心急想实现功能,也可以去云市场里找第三方的服务。亲测也是可用的。这里贴一个,类似的都可以。
当申请到权限之后,调用就很简单了。只需要跟着官方的文档来,阿里云官方支持了语言的SDK,只要对应地复制到自己代码,配置好 AccessKey 和短信签名、模板即可。
登录 / 未登录过自动注册
登录逻辑
如上图,当用户收到验证码并且输入之后,点击登录按钮就是另一个接口了。
这时候先会去login_code(自我吐槽一下,其实验证码用 captcha 这个单词才对)这个表查询验证码和手机是否对的上,如果对得上的话就再查询 users 表中是否有该用户的记录。如果没有,就要先创建新用户再返回数据。这里会随机生成一个字符串,作为用户的token,在之后涉及到用户权限的接口中这个可以当成用户的唯一标识,放在请求头中。
//随机生成指定长度的字符串
const randomStrin = function (length) {
var str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
var result1 = "";
for (var i = length; i > 0; --i)
result1 += str[Math.floor(Math.random() * str.length)];
return result1;
};
此外,还可以在创建新用户这里一些其它的功能。
比如说我的项目有一些社交成分,这里的设计就是:若是用户通过别人的分享完成注册的,分享的那个人就可以获得相对应的积分。下面贴一些基本逻辑和sql语句可以供参考。
//篇幅所限,非完全代码,系基本逻辑和主要sql语句。
let myphone = ctx.request.body.phone;
let mycodemsg = ctx.request.body.code;
let isCode =
`select * from login_code where phone = ${myphone} and code = ${mycodemsg}`,
//若不存在返回flase
if (!isCode) {
//验证码不正确返回错误提示
ctx.body = "验证码不正确";
return;
}
// 判断是否注册过
let isres = `SELECT * FROM users WHERE phone='${myphone}'`;
//用户表不存在放回flase
if (isres) {
let loginSql = `select * from users where phone = ${myphone}`;
//注册过返回用户数据
ctx.body = result;
} else {
let myname = myphone;
let mytoken = randomStrin(16);
let mycode = randomStrin(8);//此处是邀请板块的邀请码,若是分享给其它用户就传这个
let myavatar = "http://localhost:8090/useravatar/avatar.png";//默认的用户头像
let resSql = `INSERT INTO users (name,phone,token,code,avatar,score) values("${myname}",${myphone},"${mytoken}","${mycode}","${myavatar}",0)`;
//新增用户
let result = `select * from users where token = "${mytoken}"`,
//返回新用户信息
});
// 此处为邀请者得积分模块
if (ctx.url.split("?")[1].split("=")[1]) {
//这里的邀请参数放在了url中
let invite_code = ctx.url.split("?")[1].split("=")[1];
let invite_setting = "SELECT invite_setting FROM setting"//这里是邀请-积分比,放在了setting表单中
let old_score_total = `SELECT score,token FROM users where code="${invite_code}"`,
let type = 1;
let new_score_total = old_score_total.score + invite_setting;
let invite_token = old_score_total.token;
let creat_time = formatTime(new Date());
let sql = `INSERT INTO score (token,type,score_change,score_total,creat_time) values("${invite_token}",${type},${invite_setting},${new_score_total},"${creat_time}")`;
let changeuser = `update users set score=${new_score_total} where token="${invite_token}"`,
//上列都是邀请-得积分板块的操作,如果有想法,在这里可以有很多种玩法
}
if (result) {
ctx.body = result;
}
}
总结
短信验证登录 / 未登录过自动完成注册——这个模式已经成为了现在很多个人开发者和小网站的登录注册主流。实操下来,你会发现最费时间和精力的不是逻辑设计和代码的开发,而是如何获得向用户发送验证码。
云服务固然方便,但是因为审核的严格也有所限制。搞一个网站备案往往需要半个月十几天的时间。所以,如果你是大学生,也想在毕设之类的项目用上短信验证的话建议先去做网站备案,才能享受到各种方便的云服务。当然了,你也可以试试看我文中列出的云市场的服务,或者是弄邮箱认证也差不多是这样的流程。
个人小项目,有许多不足,欢迎你指正,与我交流哦~