一、辅助代码
在server/dbs/config.js里定义redis、smtp等相关配置:
module.exports = {
dbs: 'mongodb://127.0.0.1:27017/student',
redis: {
get host() {
return '127.0.0.1'
},
get port() {
return 6379
}
},
smtp: {
get host() {
return 'smtp.qq.com'
},
get user() {
return 'xxxx@qq.com'
},
get pass() {
return 'xxxxxxxxxxxxx'
},
get code() {
return () => {
return Math.random().toString(16).slice(2, 6).toUpperCase()
}
},
get expire() {
return () => {
return new Date().getTime() + 60 * 1000
}
}
}
}
在server/dbs/models/users.js定义User表,用来存储用户信息:
const mongoose = require('mongoose');
//定义一个描述表结构的Schema
let userSchema = new mongoose.Schema({
username: {
type: String,
unique: true,
require: true
},
password: {
type: String,
require: true
},
email: {
type: String,
require: true
}
})
//把这个 schema 编译成一个 Model,和表联系起来,model 是我们构造 document 的 Class
module.exports = mongoose.model('User', userSchema)
在入口文件server/index.js里做连接数据库、配置路由等工作
const Koa = require('koa')
const { Nuxt, Builder } = require('nuxt')
const mongoose = require('mongoose')
const consola = require('consola')
const config = require('../nuxt.config.js')
const dbConfig = require('./dbs/config')
const json = require('koa-json')
const bodyParser = require('koa-bodyparser')
const users = require('./interface/users')
const app = new Koa()
config.dev = app.env !== 'production'
//koa-bodyparser:处理程序之前,在中间件中对传入的请求体进行解析
app.use(bodyParser({
extendTypes: ['json', 'form', 'text']
}))
//koa-json:让 Koa2 支持响应 JSON 数据
app.use(json())
//连接数据库
mongoose.connect(dbConfig.dbs, {
useNewUrlParser: true
})
async function start() {
// Instantiate nuxt.js
const nuxt = new Nuxt(config)
const {
host = process.env.HOST || '127.0.0.1',
port = process.env.PORT || 3000
} = nuxt.options.server
// Build in development
if (config.dev) {
const builder = new Builder(nuxt)
await builder.build()
} else {
await nuxt.ready()
}
app.use(users.routes(), users.allowedMethods())
app.use((ctx) => {
ctx.status = 200
ctx.respond = false // Bypass Koa's built-in response handling
ctx.req.ctx = ctx // This might be useful later on, e.g. in nuxtServerInit or with nuxt-stash
nuxt.render(ctx.req, ctx.res)
})
app.listen(port, host)
consola.ready({
message: `Server listening on http://${host}:${port}`,
badge: true
})
}
start()
二、核心代码
在server/interface/users.js里定义接口:
const Router = require('koa-router')
const Redis = require('koa-redis')
const nodemailer = require('nodemailer')
const User = require('../dbs/models/users')
const Email = require('../dbs/config')
//新建router实例
let router = new Router({
prefix: '/users'
})
//新建redis客户端
const Store = new Redis().client
// signup 注册接口实现
router.post('/signup', async (ctx, next) => {
const { code, username, password, email } = ctx.request.body
//校验code
if (code) {
const saveCode = await Store.hget(`nodemail:${username}`, 'code')
const saveExpire = await Store.hget(`nodemail:${username}`, 'expire')
if (code === saveCode) {
if (new Date().getTime() - saveExpire > 0) {
ctx.body = {
code: -1,
msg: '验证码已过期,请重新尝试'
}
return false
}
} else {
ctx.body = {
code: -1,
msg: '请填写正确的验证码'
}
return false
}
} else {
ctx.body = {
code: -1,
msg: '请填写验证码'
}
return false
}
//校验 username是否已经存在数据库
const name = await User.find({ username })
if (name.length) {
ctx.body = {
code: -1,
msg: '用户名已存在'
}
return
}
// 把注册信息username、password、email存数据库
const user = await User.create({username, password, email})
try {
user.save()
ctx.body = {
code: 0,
msg: '注册成功',
}
return
} catch (e) {
ctx.body = {
code: -1,
msg: '服务端错误'
}
return
}
})
//verify 发送验证码接口实现
router.post('/verify', async (ctx, next) => {
//校验是不是一分钟之内
let username = ctx.request.body.username;
let email = ctx.request.body.email;
const saveExpire = await Store.hget(`nodemail:${username}`, 'expire');
if (saveExpire && new Date().getTime() - saveExpire < 0) {
ctx.body = {
code: -1,
msg: '验证请求过于频繁,1分钟内1次'
}
return false
}
//发送端信息
let transporter = nodemailer.createTransport({
service: 'qq',
port: 465, // SMTP 端口
secureConnection: true, // 使用了 SSL
auth: {
user: Email.smtp.user,
pass: Email.smtp.pass
}
});
//接受端信息
let ko = {
code: Email.smtp.code(),
expire: Email.smtp.expire(),
email,
user: username
}
//邮件信息
let mailOptions = {
from: `《李赵测试网站》<${Email.smtp.user}>`,
to: ko.email,
subject: '李赵测试网站验证码',
html: `${ko.user}您好,您正在《李赵测试网站》注册,验证码是:${ko.code}`
};
//发送邮件
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log(error);
} else {
Store.hmset(`nodemail:${ko.user}`, 'code', ko.code)
Store.hmset(`nodemail:${ko.user}`, 'expire', ko.expire)
Store.hmset(`nodemail:${ko.user}`, 'email', ko.email)
}
});
//ctx返回值
ctx.body = {
code: 0,
msg: '验证码发送成功'
}
})
module.exports = router