mongod
redis-server
export default {
dbs: 'mongodb://127.0.0.1:27017/student',
redis: {
get host() {
return '127.0.0.1'
},
get prot() {
return 6379
}
},
//邮箱服务
smtp: {
get host() {
return 'smtp.qq.com'
},
get user() {
return 'qq号码'
},
get pass() {
return '授权码'
}
},
//生成邮箱验证码
get code() {
return () => {
return Math.random().toString(16).slice(2, 6).toUpperCase()
}
},
//验证码过期时间
get expire() {
return () => {
return new Date().getTime() + 60 * 60 * 1000
}
}
}
//定义模型(建表)
import mongoose from 'mongoose'
const Schema = mongoose.Schema
const UserSchema = new Schema({
username: {
type: String,
unique: true,
require: true
},
password: {
type: String,
require: true
},
email: {
type: String,
require: true
}
})
export default mongoose.model('User', UserSchema)
//配置 axios
import aioxs from 'axios'
//基础配置
const instance = aioxs.create({
baseURL: `http://${process.env.HOST || 'localhost'}:${process.env.PORT || 3000}`,
timeout: 1000,
headers: {
}
})
export default instance
2.配置passport
koa-passport
这是这个项目中很重要的一个中间件。大概逻辑就是,用户登录,它就帮忙把用户信息存在session里,在浏览器端也会生成对应的cookie,还提供了几个方法ctx.isAuthenticated() 用户是否登录,ctx.login()用户登录, ctx.logout()用户退出。
passport.js是Nodejs中的一个做登录验证的中间件,极其灵活和模块化,并且可与Express、Sails等Web框架无缝集成。Passport功能单一,即只能做登录验证,但非常强大,支持本地账号验证和第三方账号登录验证(OAuth和OpenID等),支持大多数Web网站和服务。
import passport from 'koa-passport'
import LocalStrategy from 'passport-local'
import UserModel from '../../dbs/models/users'
passport.use(new LocalStrategy((username, password, done) => {
let where = {
username
}
UserModel.findOne(where).then((res) => {
if (res != null) {
if (res.password === password) {
return done(null, res)
} else {
return done(null, false, '密码错误')
}
} else {
return done(null, false, '用户不存在')
}
})
}))
passport.serializeUser((user, done) => {
done(null, user)
})
passport.deserializeUser((user, done) => {
return done(null, user)
})
export default passport
//定义接口
import Router from 'koa-router';
import Redis from 'koa-redis';
import nodeMailer from 'nodemailer';
import User from '../dbs/models/users'
import Passprot from './utils/passport'
import Email from '../dbs/config'
import axios from './utils/axios'
//创建接口
let router = new Router({
prefix: '/users'
})
let Store = new Redis().client
//注册接口
router.post('/singup', async (ctx, next) => {
// 获取用户名,密码,邮箱,验证码
const {
username,
password,
email,
code
} = ctx.request.body;
// 校验 验证码
if (code) {
//ridis 中取出验证码
const saveCode = await Store.hget(`nodemail:${username}`, 'code')
const saveExpier = await Store.hget(`nodemail:${username}`, 'expire')
if (code === saveCode) {
if (new Date().getTime() - saveExpier > 0) {
ctx.body = {
code: -1,
msg: '验证码已过期,请重新尝试'
}
return false
}
} else {
ctx.body = {
code: -1,
msg: '请填写正确的验证码'
}
}
} else {
ctx.body = {
code: -1,
msg: '请填写验证码'
}
}
//验证数据库中是否已经存在该用户
let user = await User.find({
username
})
if (user.length) {
ctx.body = {
code: -1,
msg: '已被注册'
}
return
}
// 用户名密码写入数据库中
let nuser = await User.create({
username,
password,
email
})
if (nuser) {
let res = await axios.post('/users/signin', {
username,
password
})
if (res.data && res.data.code === 0) {
ctx.body = {
code: 0,
msg: '注册成功',
user: res.data.user
}
} else {
ctx.body = {
code: -1,
msg: 'error'
}
}
} else {
ctx.body = {
code: -1,
msg: '注册失败'
}
}
})
// 登录接口
router.post('/signin', async (ctx, next) => {
// Passport 本地登录 这是固定用法
return Passprot.authenticate('local', function (err, user, info, status) {
if (err) {
ctx.body = {
code: -1,
msg: err
}
} else {
if (user) {
ctx.body = {
code: 0,
msg: '登录成功',
user
}
// Passport中间件带的ctx.login
return ctx.login(user)
} else {
ctx.body = {
code: 1,
msg: info
}
}
}
})(ctx.next)
})
//验证码验证
router.post('/verify', async (ctx, next) => {
let username = ctx.request.body.username
const saveExpier = await Store.hget(`nodemail:${username}`, 'expire')
if (saveExpier && new Date().getTime() - saveExpier < 0) {
ctx.body = {
code: -1,
msg: '请求过于频繁 一分钟内一次'
}
return false
}
// 创建mtp 服务
let transporter = nodeMailer.createTransport({
host: Email.smtp.host,
port: 587,
secure: false,
auth: {
user: Email.smtp.user,
pass: Email.smtp.pass
}
})
let ko = {
code: Email.smtp.code(),
expire: Email.smtp.expire(),
email: ctx.request.body.email,
user: ctx.request.body.username
}
let mailOptions = {
from: `"认证邮件" <${Email.smtp.username}>`,
to: ko.email,
subject: '<注册码>',
html: `您的注册吗是${ko}`
}
await transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log('error');
} else {
Store.hmset(`nodemail:${ko.user}`, 'code', ko.code, 'expire', ko.expire, 'email', ko.email)
}
})
ctx.body = {
code: 0,
msg: '验证码已发送'
}
})
//验证码验证
router.post('/verify', async (ctx, next) => {
let username = ctx.request.body.username
const saveExpier = await Store.hget(`nodemail:${username}`, 'expire')
if (saveExpier && new Date().getTime() - saveExpier < 0) {
ctx.body = {
code: -1,
msg: '请求过于频繁 一分钟内一次'
}
return false
}
// 创建mtp 服务
let transporter = nodeMailer.createTransport({
host: Email.smtp.host,
port: 587,
secure: false,
auth: {
user: Email.smtp.user,
pass: Email.smtp.pass
}
})
let ko = {
code: Email.smtp.code(),
expire: Email.smtp.expire(),
email: ctx.request.body.email,
user: ctx.request.body.username
}
let mailOptions = {
from: `"认证邮件" <${Email.smtp.username}>`,
to: ko.email,
subject: '<注册码>',
html: `您的注册吗是${ko}`
}
await transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log('error');
} else {
Store.hmset(`nodemail:${ko.user}`, 'code', ko.code, 'expire', ko.expire, 'email', ko.email)
}
})
ctx.body = {
code: 0,
msg: '验证码已发送'
}
})
//退出接口
router.get('/exit', async (ctx, next) => {
// passport 自带logout方法,会清除session cookie
await ctx.logout()
if (!ctx.isAuthenticated()) {
ctx.body = {
code: 0
}
} else {
ctx.body = {
code: -1
}
}
})
//获取用户名
router.get('/getUser', async (ctx, next) => {
if (ctx.isAuthenticated()) {
const {
username,
email
} = ctx.session.Passprot.user
ctx.body = {
user: username,
email
}
} else {
ctx.body = {
user: '',
email: ''
}
}
})
export default router
// 配置路由
import mongoose from 'mongoose'
import bodyParser from 'koa-bodyparser'
import session from 'koa-generic-session'
import Redis from 'koa-redis'
import json from 'koa-json'
import dbConfig from './dbs/config'
import passport from './interface/utils/passport'
import users from './interface/users'
import passprot from './interface/utils/passport'
// 配饰session
app.keys = ['xc', 'xcxc']
app.proxy = true
app.use(session({
key: 'xc',
prefix: 'xc:id',
store: new Redis()
}))
//处理post
app.use(bodyParser({
extendTypes: ['json', 'from', 'text']
}))
app.use(json())
//链接数据库
mongoose.connect(dbConfig.dbs, {
useNewUrlParser: true
})
//处理passport
app.use(passprot.initialize())
app.use(passprot.session())
//引入路由
app.use(users.routes()).use(users.allowedMethods())