Vue+jsonwebtoken+express-jwt实现登录验证

闻人浩波
2023-12-01

express中的使用

安装express-jwt npm install express-jwt

配置express-jwt

const expressJwt = require('express-jwt');
app.use(expressJwt({
  secret: 'userLogin',  // 签名的密钥
  algorithms: ["HS256"] // 设置算法(官方文档上没有写这个,但是不配置的话会报错)
}).unless({
  path: ['/login', '/register/create', '/register/upload']  // 不经过 Token 解析的路径
}))

安装jsonwebtoken npm install jsonwebtoken

jsonwebtoken使用

// 引入jsonwebtoken
const jwt = require('jsonwebtoken')
// 在返回的时候使用jsonwebtoken返回一个token
// 一般是作为登录成功的返回值
req.session.regenerate(err => {
      if (err) {
        return res.json({ret_code: 2, ret_msg: '登录失败'});
      }
      // 注意默认情况 Token 必须以 Bearer+空格 开头
      const token = 'Bearer ' + jwt.sign(
        {
          user_id: data[0].dataValues.user_id,
          isLogin: true
        },
        'userLogin'
      )
      return res.send({
        success: true,
        token: token
      })
    }

验证失败的设置

// error handler
app.use(function (err, req, res, next) {
  console.log(err)
  // 根据错误信息判断是否是未登录直接访问
  if (err.name === 'UnauthorizedError') {
    //  可以根据自己的业务逻辑来处理
    return res.status(401).send('没有权限');
  }
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.send('error');
});

其余的配置

app.use((req, res, next) => {
  // 由于express-jwt需要配合前台发送的cookie使用,所以要把Access-Control-Allow-Credentials设置为true
  // 设置Access-Control-Allow-Credentials为true后,Access-Control-Allow-Origin不能使用通配符,所以我改成req.get("origin")
  // 允许的请求主机名及端口号 也可以用通配符*, 表示允许所有主机请求
  res.setHeader('Access-Control-Allow-Origin', req.get("origin"));
  // 允许请求携带cookie
  res.setHeader('Access-Control-Allow-Credentials', true);
  // 允许的请求方式
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
  // 允许的请求头 express-jwt的cookie是使用Authorization所以需要允许Authorization通过
  res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type,Authorization');
  res.setHeader('Access-Control-Expose-Headers', 'Authorization')
  next();
});

Vue中的使用

express-jwt需要前端发送一段头部信息,才可以进行验证,所以前端需要对后台发送的token进行保存,在每次请求之前将token添加到头部中

首先封装一个设置cookie的代码cookie.js

// 设置cookie
export function setCookie(name, value, iDay) {
  /*当时间参数存在的时候*/
  if (iDay) {
    /*设置过期时间*/
    var oDate = new Date();
    oDate.setDate(oDate.getDate() + iDay);
    document.cookie = name + '=' + value + ';expires=' + oDate;
  } else {
    /*否者默认浏览器关闭过期*/
    document.cookie = name + '=' + value;
  }
}

// 获取cookie
export function getCookie(name) {
  /*将获取到的字符串变成数组纯在arr中*/
  /*得到的数据格式是这样的a=11; b=12*/
  var arr = document.cookie.split('; ');
  for (var i = 0; i < arr.length; i++) {
    /*再拆分一次*/
    var arr2 = arr[i].split('=');
    //判断arr2[0]是否是要读取的Cookie
    if (arr2[0] === name) {
      return arr2[1];
    }
  }
  return '';
}

axios的请求拦截和配置

import axios from 'axios'
import { getCookie } from './cookie'
import router from '../router'
import {MessageBox} from 'element-ui'
export function request(config) {
  const ins = axios.create({
    baseURL: 'http://127.0.0.1:3000',
    withCredentials: true, // 这个必须设置,不然无法跨域传递信息
    // crossDomain: true
  })
  // request拦截器  之后每个请求都会先查找token,如果token存在则会带上一个token
  ins.interceptors.request.use(response => {
    let token = getCookie('userLogin'); //获取Cookie
    if (token) {
    // 将cookie保存到头部的Authorization中,必须是Authorization
      response.headers['Authorization'] = token
    }
    axios.defaults.withCredentials = true
    return response
  }, error => {
    return Promise.reject(error)
  })
  // response拦截器
  ins.interceptors.response.use(response => {
    return response.data
  }, error => {
  // 判断错误类型,如果是401则是没有权限,跳转到登录界面
    if (error.response.status === 401) {
      MessageBox('请先登录帐号', '提示', {
        confirmButtonText: '确定',
        type: 'warning'
      }).then(() => {
        router.push({
          path: '/login'
        })
      });

    }
    return Promise.reject(error)
  })
  return ins(config)
}

api接口代码(示例)

import { request } from '../utils/request'

export function getUser() {
  return request({
    url: 'getUser',
    method: 'get',
  })
}

Vue请求接口的代码

import { getUser } from '../api/index'
created() {
// 验证成功会获取所有用户信息,验证失败会跳转到登录页面
    this.getUser()
  },

至此,只要前台请求接口,后台都会根据头部信息进行验证,验证成功以后就可以访问接口,验证失败会返回错误信息,前台可以在拦截器的部分进行自己的一些逻辑操作

 类似资料: