基础配置
我的项目是react + node + MongoDB ,首先邮箱验证码的发送需要开启SMTP服务,这里我就不做过多赘述了,挺简单的,给大家一个地址照着这个做就行:
https://jingyan.baidu.com/article/c35dbcb0eb01428917fcbc77.html
然后,我们要在项目中安装
nodemailer
中间件,这个是发送邮箱验证码必不可少的
npm i nodemailer
思路详解
先看看我的项目目录结构
下面展示的文件都只展示与邮箱验证码发送有关的主要代码
1. 入口:
app.js
首先 建立一个express 服务, 连接数据库, 引入路由
const express = require('express')
var bodyParser = require('body-parser')
var router = require('./router') // 引入路由
const db = require('./db/connect') // 链接数据库
const app = express()
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json()) // 这三行为解析接口传参
app.use(router)
app.listen(8000, () => {
`server is running at port 8000 success~~~`
})
2.
连接数据库
./db/connect.js
const mongoose = require('mongoose')
// 连接数据库
mongoose.connect('mongodb://localhost/usertest', { useNewUrlParser: true, useUnifiedTopology: true })
var db = mongoose.connection // 数据库的链接对象
db.on('error', console.error.bind(console, 'connection error:'))
db.once('open', function() {
console.log('数据库链接成功')
})
3.
用户对象模块
./db/model/userMoldel.js
const mongoose = require('mongoose')
var Schema = mongoose.Schema
// 设计表结构
var userSchema = new Schema({
username: {
type: String,
required: true
},
studentid: {
type: String,
required: true
}
})
// 将表结构发布为模型
var User = mongoose.model('User', userSchema)
module.exports = User
4.
路由模块
router.js
var express = require('express')
var router = express.Router()
const mailSend = require('../utils/mail')
const User = require('../db/model/userModel')
// 发送邮箱验证码
router.post('/getMailCode', (req, res) => {
let { mail } = req.body
if (mail) {
let code = parseInt( Math.random() * 10000 ) // 随机验证码
// 生成验证码时将验证码存入数据库中
User.findOne({ email: mail }, (err, data) => {
if (data !== null) { //非第一次登录
User.findOneAndUpdate(...) //找到数据库中的当前用户的信息并更新当前testcode
.then(() => {
// 发送验证码
mailSend.send(mail, code).then(() => {
res.send({err: 0, msg: '验证码发送成功且 已存入数据库'})
}).catch((err) => {
console.log(err)
res.send({err: -1, msg: '验证码发送失败'})
})
})
.catch((err) => {
console.log(err);
})
}
else {
// 第一次登录 数据库中还没有用户信息
User.insertMany(...) // 把tescode存入数据库
.then(() => {
// 发送验证码
mailSend.send(mail, code).then(() => {
res.send({err: 0, msg: '验证码发送成功且 已存入数据库'})
}).catch((err) => {
console.log(err)
res.send({err: -1, msg: '验证码发送失败'})
})
})
.catch((err) => {
console.log(err);
})
}
})
else {
res.send({err: -1, msg: '参数错误'})
}
})
// 用户登录时判断验证码是否正确
router.post('/log', (req, res) => {
// console.log(req.body)
if (req.body) {
let { email, testcode } = req.body
// 判断验证码是否正确
// 读取到数据库中的验证码
User.findOne({ email: email }, (err, data) => {
if (err) {
return res.status(500).send('Server error.')
}
if (data.testcode !== null) {
// 数据库里有testcode时
// 判断testcode是否正确
// console.log(data.testcode);
if (!(data.testcode === testcode)) { //验证码是否正确
return res.send({ err: -4, msg: '验证码错误' })
}
else {
// 验证码正确时 将表单数据存入数据库并成功登录
}
}
})
}
})
5.邮件发送模块
utils/mail.js
"use strict";
const nodemailer = require('nodemailer')
// 创建一个SMTP客户端对象
let transporter = nodemailer.createTransport({
host: "smtp.qq.com", // 发送方邮箱 qq 通过lib/wel-konw
port: 465,
secure: true, // true for 465, false for other ports
auth: {
user: '1447478506@qq.com', // 发送方邮箱地址
pass: '**************' // mtp 验证码 这个有了才可以发送邮件,可以qq邮箱去查看自己的码
}
})
function send(mail, code) {
// 邮件信息
let mailobj = {
from: '"何梦梦" <1447478506@qq.com>', // sender address
to: mail, // list of receivers
subject: "何梦梦", // Subject line
text: `您的验证码是${code},有效期5分钟`
}
return new Promise((reslove, reject) => {
// 发送邮件
transporter.sendMail(mailobj, (err, data) => {
if (err) {
reject()
} else {
reslove()
}
})
})
}
module.exports = { send }
到这里基本就完成了 。
整体思路
客户端点击获取验证码按钮时,向服务端发送请求,服务端接收到请求后去调用mailSend去发送验证码,每生成一次验证码就将验证码存入数据库,然后客户端在登录的时候向服务端发送请求同时 在服务端中 服务端去读取数据库中的验证码和当前客户端表单中发送过来的验证码作比对,如果验证码正确则成功登录,验证码不正确提示验证码错误
。
这里有一个非常需要注意的点就是
:
当服务端在每次生成验证码并将其存入数据库时,假如用户是第一次登录,那么数据库中目前是什么数据都没有的,所以我们就将当前用户信息存入数据库,但用户非第一次登录时,我们只需要查找到当前该用户的信息并进行验证码的更新即可
。