Vue登录登出以及JWT认证

数据模型

主要用户名,密码,邮箱,头像,身份

const mongoose = require('mongoose')

const schema = new mongoose.Schema({
  username: {
    type: String,
    require: true
  },
  email: {
    type: String,
    require: true
  },
  password: {
    type: String,
    require: true
  },
  avator: {
    type: String
  },
  identify:{
    type: Number,
    require: true
  },
  createdAt: {
    type: String,
    default: Date.now()
  },
  updateAt: {
    type: String,
    default : Date.now()
  }
})

module.exports = mongoose.model('user', schema)
View Code

首先注册接口代码

router.post('/register', async ctx => {
  const {username, password, email, avatar, identify} = ctx.request.body
  
  try {
    const user = await UserModel.findOne({email})
    if (user) {
      return ctx.body = {code: 1, msg: '邮箱存在'}
    }
    const newUser = new UserModel({username, password, email, avatar, identify})
    const res = await newUser.save()

    return ctx.body = {code:0, data: res }
  } catch(err) {
    return ctx.body = {code:0, msg: '出错啦'}
  }
})

首先对密码进行加密加盐

加密方案1

utility进行字符串加密

const utility = require('utility')

exports.md5 = pwd => {
  const salt = '!@#$%' 
  return utility.md5(pwd + salt)
}
const newUser = new UserModel({username, email, avatar, identify, password: md5(password)})

登录接口代码

router.post('/login', async ctx => {
  const {email, password} = ctx.request.body

  const res = await UserModel.findOne({email})
  if (!res) return ctx.body = {code: 1, msg:'用户不存在'}

  if (res.password !== md5(password)) return ctx.body = {code:1, msg: '密码错误'}
  const user = {username: res.username, email: res.email, identity: res.identify, avator: res.avatar}
  return ctx.body = {code: 0 , data: user}

})

安装jwt

jsonwebtoken

返回token

const token = await jwt.sign({username: user.username, id: user._id, email: user.email, timeout: `${(new Date().getTime() + 60*60*10)}`}, config.secret, {expiresIn: 3600})
return ctx.body = {code: 0 , data: Object.assign(user, {token: `Bearer ${token}`})}

使用koa中间件机制检测用户是否登录或者token是否过期

const jwt = require('jsonwebtoken')
const UserModel = require('../db/models/user')
const config = require('../config/config')
const check = async (ctx, next) => {
  const url = ctx.request.url
  // 登录,注册不做token校验
  if (url === '/user/login' || url === '/user/register') await next() 
  else {
    const token = ctx.request.headers['authorization'].split(' ')[1]
    // 解析token
    const payload = await jwt.verify(token, config.secret)
    const date = new Date().getTime()
    const {email, timeout} = payload
    if (date > parseInt(timeout)) return ctx.body = {code: 11, msg: 'token过期'}
    // 查询用户是否存在
    const user = await UserModel.findOne({email: email})
    if (!user) return ctx.body = {code: 10, msg: '用户没有登录'}
    
    else await next()
  }
}

module.exports = check

Vue前端

登录之后获得token存储到本地,并且解析token把用户信息存储到Store中

const user = jwtDecode(token)
window.localStorage.setItem('token', token)
this.setUser(user)
this.setIsAutnenticated(!isEmpty(user))
this.$router.push('/')

路由守卫

根据本地是否有token判断用户是否登录

router.beforeEach((to, from, next) => {
  const isLogin = !!window.localStorage.getItem('token')
  if (to.path === '/login' || to.path === '/register') next()
  else {
    isLogin ? next() : next({ name: 'login' })
  }
})

请求拦截

把token发生给服务器

axios.interceptors.request.use(config => {
  // 添加Loading
  startLoading()
  const token = window.localStorage.getItem('token')
  if (token) {
    config.headers['authorization'] = token
  }
  return config
}, err => {
  return err
})
原文地址:https://www.cnblogs.com/sonwrain/p/10823049.html