Vue项目中存储与使用后端传递过来的token

作者:栖木时间:2026-10-26 11:46:48浏览:271

本文详细记录了在Vue项目中如何存储和使用后端传递的token。后端通过express-jwt中间件验证token,前端在登录时将token存入localStorage。文章重点讲解了如何利用Vue Router的beforeEach实现路由守卫,以及通过Axios请求和响应拦截器处理token过期导致的401状态码(实际为0)问题,确保用户自动跳转登录页。

前言

以往通常仅在Postman中进行Token验证测试,本文将记录在真实Vue项目中存储和使用Token的具体流程。

后端关于token的设置

在app.js中配置Token验证逻辑。

const expressJWT = require('express-jwt')
const app = express();
const config = require('./config')
app.use(expressJWT({secret: config.jwtSecretKey}).unless({path: [/^\/api\/users/]}))

const testRouter = require('./routes/testToken')
app.use('/my', testRouter)

config文件中定义了密钥,此处省略具体代码。

unless配置指定了无需Token验证的路由,即以/api/users开头的链接除外。

使用的testToken.js模块如下:

const express = require('express');
const router = express.Router();

const test = require('../router_handler/testToken')

router.get('/current', test.test)

module.exports = router

采用模块化写法,实际路由处理函数位于/router_handler/testToken.js中,代码如下:

const db = require('../db/index');

exports.test = (req, res) => {
    const sql = 'select * from users where id = ?'
    db.query(sql, req.user.id, (err, results) => {
        if(err) return res.send({status: 404, message: err})
        if(results.length !== 1) return res.send({status: 404, messsage: '获取用户信息失败,需重新登录'})
        res.json(results[0])
    })
    // res.send(req)
}

该函数主要用于获取用户信息,通过MySQL根据ID查询数据。

关键步骤:经过上述配置后,访问非/api/users开头的链接时均需验证Token。Token在用户登录时生成,具体实现在用户登录处理函数user.js中:

// 用户登录的处理函数
exports.login = (req, res) => {
    const userinfo = req.body
    const sql = 'select * from users where name = ?'
    db.query(sql, userinfo.name, (err, results) => {
        if(err) return res.send({status: 404, message: err.message})
        if(results.length !== 1) return res.status(404).json('用户不存在!')
        const compareResults = bcrypt.compareSync(userinfo.password, results[0].password)
        if(!compareResults) return res.status(404).json('密码错误!')
        const user = {
            id: results[0].id,
            name: results[0].name,
            avatar: results[0].avatar,
            identify: results[0].identify
        }
        const tokenStr = jwt.sign(user, config.jwtSecretKey, {expiresIn: '10h'})
        res.json({
            status:200, 
            message: '登录成功', 
            // result: results[0], 
            token: 'Bearer ' + tokenStr
        })
    })
}

省略无关代码,注意tokenStr变量即为存储的Token值,通过响应返回。

总结后端存储Token的流程:

  • 编写登录函数,向页面响应Token字符串;
  • 在入口文件(app.js)中设置需要提供Token的路由,并提供解析Token字符串的密钥;
  • 编写对应的路由函数,处理请求。

至此,后端关键要点已阐述完毕,接下来进入前端Token的存储部分。

前端页面取用token

前端在登录时应存储后端响应的Token,以实现路由守卫和免登录功能。

token存储

通过Ajax请求路由地址,获取res.data中的Token字符串,并存储至浏览器中。步骤和写法相对固定。

代码编写于Login.vue中,如下:

methods: {
    submitForm(formName) {
      this.$refs[formName].validate(valid => {
        if (valid) {
          this.$axios
            .post("/users/login", this.loginUser)
            .then(res => {
                // console.log(res)
                //token
                const { token } = res.data
                localStorage.setItem("eleToken", token)
             
                this.$router.push("/index");
            });
        } else {
          console.log("error submit!!");
          return false;
        }
      });
    }
  }

const { token } = res.data通过解构赋值方式从响应数据中提取Token。

localStorage.setItem("eleToken", token)将Token存储至浏览器本地存储。

前言

前端使用token实现路由守卫

后端代码中的unless相当于路由守卫,但前端也需实现此功能,否则无需登录即可访问网站内容,这显然不合理。

前端实现代码如下,编写于router.js中:

import Vue from 'vue'
import VueRouter from 'vue-router'
import Index from './views/Index.vue'
import Register from './views/Register.vue'
import NotFound from './views/404.vue'
import Login from './views/Login.vue'

Vue.use(VueRouter)

const router = new VueRouter({
    mode: 'history',
    base: process.env.BASE_URL,
    routes: [
        { path: '*', name: '/404', component: NotFound },
        { path: '/', redirect: '/index' },
        { path: '/register', name: 'register', component: Register },
        { path: '/index', name: 'index', component: Index },
        { path: '/login', name: 'login', component: Login },
    ]
})

// 路由守卫
router.beforeEach((to, from, next) => {
    const isLogin = localStorage.eleToken ? true: false
    if(to.path == '/login' || to.path == '/register'){
        next()
    }else {
        isLogin ? next() : next('/login')
    }
})

export default router

关注路由守卫部分的代码逻辑。

使用Vue Router中的beforeEach函数。

具体逻辑如下:

  1. 定义isLogin(布尔值),若浏览器localStorage中存在eleToken对象,则值为true,否则为false;
  2. 确定无需拦截的路由:to.path == '/login' || to.path == '/register',即登录和注册页面直接放行,调用next();
  3. 对于被拦截的路由,判断isLogin是否为true,若是则说明已登录且有Token,直接放行;若为false,则跳转至登录路由。

请求拦截和响应拦截

还需解决Token过期判断问题。后端设置Token有效期为10小时,过期后应重新登录。

此处代码编写于单独的http.js文件中,先展示代码:

import axios from "axios";
import { Message, Loading } from 'element-ui';
import router from "./router"

let loading;
function startLoading(){
    loading = Loading.service({
        lock: true,
        text: '数据加载中',
        background: 'rgba(0,0,0,0.7)'
    })
}

function endLoading(){
    loading.close();
}

// 请求拦截
axios.interceptors.request.use(config => {
    startLoading();
    if(localStorage.eleToken){
        // 设置统一的请求头
        config.headers.Authorization = localStorage.eleToken
    }
    return config
}, error => {
    return Promise.reject(error)
})

//响应拦截
axios.interceptors.response.use(response => {
    endLoading();
    return response
}, error => {
    // 错误提醒
    endLoading();
    Message.error(error.response.data)

    // 获取错误状态码
    const {status} = error.response
    if(status == 401){
        Message.error("token失效,请重新登录")
        localStorage.removeItem('eleToken')
        router.push('/login')
    }
    return Promise.reject(error)
})

export default axios

关注后续的请求拦截和响应拦截逻辑。

分为两步:

请求拦截:当发送请求时,判断localStorage中是否存储了eleToken,若有则将其写入请求头;响应拦截:当Token过期时,页面会响应401错误状态码,此时需清除过期Token并跳转至登录页面。

注意,此处有一个坑,博主耗费一下午才解决,原以为:

页面会响应一个401的错误状态码

是正确的,但测试发现Token过期后并未跳转至登录页。打印status后发现该值等于0,因此响应拦截的正确写法应为:

//响应拦截
axios.interceptors.response.use(response => {
    endLoading();
    return response
}, error => {
    // 错误提醒
    endLoading();
    Message.error(error.response.data)
    console.log(error.response)

    // 获取错误状态码
    const {status} = error.response
    console.log(status)
    if(status === 0){
        Message.error("token失效,请重新登录")
        localStorage.removeItem('eleToken')
        // console.log(error)
        router.push('/login')
    }
    return Promise.reject(error)
})

修正状态码判断后,跳转功能恢复正常。

至此,前后端Token的使用流程已顺畅运行。

总结

本文介绍了Vue项目中存储与使用后端传递Token的方法,更多相关内容可搜索本站往期文章或继续浏览后续文章,希望大家支持本站!

作者最新文章