Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
前言
很多网站都会有用户注册这一个功能模块,其中大多数网站都会让用户填写手机号,然后通过手机验证码来实现用户的注册。但是大家都知道手机验证码都会收取一定的费用,所以有一些网站可能资金不够,但是又想尽大可能的留住用户,所以他们就采用使用邮箱验证码的方式来进行注册。
1.采用的技术栈
前端:vue2.x
后端:Express+mongoose
数据存储:mongodb
2.整体实现思路
(1)前端收集用户信息,包括邮箱。
(2)用户点击获取邮箱验证码,调取后端获取验证码的接口。
(3)后端生成随机验证码,发送到用户邮箱,且将此验证码保存到数据库中,并设置一定的失效时间。
(4)用户填写验证码,调用注册接口。
(5)后端接收验证码,与数据库中相对比,成功则注册,否则验证码错误。
3.具体实现代码
(1)在express项目中安装邮件发送模块中间件
npm install nodemailer
npm install nodemailer-smtp-transport
(2)定义获取验证码接口
我的项目对路由进行了封装,在routes文件夹下面新建了route.js文件,作为路由入口,定义获取验证码接口如下:
//routes/route.js
const user = require("./user"); // 用户相关路由模块
router.post("/user/emailCode", user.emailCode); // 获取邮件验证码
(3)编写获取验证码接口方法
//routes/user.js
const User = require("../database/models/user"); // 用户数据库模型
const Code = require("../database/models/code"); // 验证码数据库模型
const nodemailer = require("nodemailer"); // 邮件发送模块
const smtpTransport = require("nodemailer-smtp-transport");
const user = {
// 获取邮箱验证码
emailCode: async (req, res) => {
/*邮件发送的基本配置*/
const transport = nodemailer.createTransport(
smtpTransport({
host: "smtp.163.com", // 服务,这里使用的是163邮箱
port: 465, // smtp端口,默认就是此 端口
secure: true,
auth: {
user: "xxx@163.com", //发件人邮箱,即你的邮箱
pass: "xxxxxxxx", // SMTP授权码,需要邮箱设置中获取
},
})
);
/* 生成验证码 */
const randomFns = () => {
// 生成6位随机数
let code = "";
for (let i = 0; i < 6; i++) {
code += parseInt(Math.random() * 10);
}
return code;
};
const regEmail =
/^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$/; //验证邮箱正则
/* 发送验证码 */
let EMAIL = req.body.email;
if (regEmail.test(EMAIL)) {
let code = randomFns();
transport.sendMail(
{
from: "lhqhacker@163.com", // 发件邮箱
to: EMAIL, // 收件列表
subject: "验证你的电子邮件", // 标题
html: `
<p>你好!</p>
<p>您正在注册小猪社区账号</p>
<p>你的验证码是:<strong style="color: #ff4e2a;">${code}</strong></p>
<p>***该验证码10分钟内有效***</p>`, // html 内容
},
function (error, data) {
if (error) {
transport.close(); // 如果没用,关闭连接池
}
}
);
/* 存储验证码到数据库中 */
const e_mail = EMAIL;
await Code.deleteMany({ e_mail });
const [data] = await Code.insertMany({ e_mail, code: code });
setTimeout(async () => {
//10分钟后失效,即删除验证码
await Code.deleteMany({ e_mail });
}, 1000 * 60 * 10);
res.json(res.setUnifyResFormat(null, "00000", "邮件发送成功"));
} else {
res.json(res.setUnifyResFormat(null, "E0001", "邮件格式错误"));
}
},
};
module.exports = user;
上面代码中只有一个emailCode方法,目的就是使用我们自己的邮箱发送验证码到用户的邮箱中去,其中涉及到有mongoose的知识需要小伙伴们自己去学习了,也可以在评论区留言。
(4)前端调用注册接口
//routes/user.js
const User = require("../database/models/user"); // 模型
const Code = require("../database/models/code");
const tokenSetAndVer = require("../utils/token"); // 设置token和校验token
const bcryptjs = require("bcryptjs"); // 密码加密
// 邮件发送模块
const nodemailer = require("nodemailer");
const smtpTransport = require("nodemailer-smtp-transport");
const user = {
// 注册
register: async (req, res) => {
/* 前端传来的基本信息 */
const username = req.body.username;
const e_mail = req.body.email;
const code = req.body.code;
const password = req.body.password;
const vire = await Code.findOne({ e_mail, code }); // 检验验证码
if (!vire) {
res.json(res.setUnifyResFormat(null, "U0001", "验证码填写错误!"));
return;
}
/* 如果验证码校验通过,则校验用户信息 */
User.findOne(
{
email: e_mail,
},
(err, doc) => {
if (doc) {
res.json(res.setUnifyResFormat("", "U0001", "邮件已被注册了!"));
return;
}
// 保存用户注册的信息到数据中
let user = new User({
username: username,
password: password,
email: e_mail,
});
// 保存用户
user.save(async (err, doc) => {
if (err) {
res.json(res.setUnifyResFormat(null, "D0001", err));
} else {
Code.deleteMany({ e_mail }); // 删除验证码
// 生成token
const token = await tokenSetAndVer.setToken(user.uid, user.role);
res.setHeader("Authorization", "Bearer " + token);
res.json(res.setUnifyResFormat(doc, "00000", "注册成功"));
}
return;
});
}
);
},
};
module.exports = user;
上面代码同样编写在user.js文件中,这个方法主要的作用就是校验验证码、生成token、存储用户到数据库中,对于token方面的之后我后续在补充。
总结
到这里邮箱验证码注册的功能基本算是实现了,这里主要借助了两个中间件。整个流程不算太复杂,还不赶紧运用到你的网站中去,有问题欢迎评论区留言。