Nuxt.js + koa2 + reids + mongoodb搭建注册登录接口

1.配置与连接mongodb

  1. server目录中新建dbs文件夹,配置config.js
  2. 包含连接数据库与使用smtp做一个邮箱验证
  3. 命令行连接mongodb
mongod
  1. 命令行连接redis服务
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
    }
  }
}
  1. dbs文件夹中新增model文件夹,配置users.js(建表)
//定义模型(建表)
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)

2.配置axios与passport

  1. 配置axios
//配置 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

3.书写接口(新建users.js)

//定义接口
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

4.index.js中引入使用接口

// 配置路由
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())

代码基本就是这些,接下来就可以测试啦

你可能感兴趣的:(Nuxt,koa,redis,mongoodb)