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

 更新时间:2023年03月17日 11:37:41   作者:栀椩  
vue作为一个单页面应用,vuex作为它的状态管理工具,它至少是可以很好的保存这个token值,下面这篇文章主要给大家介绍了关于vue项目中存储与使用后端传递过来的token的相关资料,需要的朋友可以参考下

前言

以前一直都是在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开头的链接都不需要token验证

用到的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值,通过res响应出来。

总结一下,后端存储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

看路由守卫后面的代码就可以了

使用的是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的文章就介绍到这了,更多相关vue存储使用后端传递的token内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 解决vue打包 npm run build-test突然不动了的问题

    解决vue打包 npm run build-test突然不动了的问题

    这篇文章主要介绍了解决vue打包 npm run build-test突然不动了的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • Vue进行数据可视化图表展示的实现示例

    Vue进行数据可视化图表展示的实现示例

    数据可视化是现代化的数据分析和展示方式,可以使数据更加直观、易于理解和传达,Vue作为一款流行的前端框架,提供了丰富的插件和工具来实现数据可视化图表展示,本文将介绍如何使用Vue和Echarts/D3.js来实现数据可视化图表展示,并提供示例代码和实际应用场景
    2023-10-10
  • Vue Vuex搭建vuex环境及vuex求和案例分享

    Vue Vuex搭建vuex环境及vuex求和案例分享

    这篇文章主要介绍了Vue Vuex搭建vuex环境及vuex求和案例分享, Vue 中实现集中式状态管理的一个 Vue 插件,对 vue 应用中多个组件的共享状态进行集中式的管理,下文相关介绍,需要的朋友可以参考一下
    2022-04-04
  • Vue3中v-for的使用示例详解

    Vue3中v-for的使用示例详解

    本文主要介绍了Vue3中v-for的使用方法,包括遍历数组、遍历对象、索引访问、嵌套遍历以及结合计算属性和方法的使用,v-for可以帮助用户动态地生成和管理列表数据,并根据需要进行复杂的DOM操作,提供了多种示例,帮助读者更好地理解和使用v-for
    2024-10-10
  • vue中的非父子间的通讯问题简单的实例代码

    vue中的非父子间的通讯问题简单的实例代码

    这篇文章主要介绍了vue中的非父子间的通讯问题简单的实例代码,需要的朋友可以参考下
    2017-07-07
  • vue-router的hooks用法详解

    vue-router的hooks用法详解

    这篇文章主要介绍了vue-router的hooks用法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-06-06
  • vue-cli构建项目下使用微信分享功能

    vue-cli构建项目下使用微信分享功能

    这篇文章主要介绍了vue-cli构建项目下使用微信分享功能,本文通过实例代码相结合的形式给大家介绍的非常详细,感兴趣的朋友跟随脚本之家小编一起学习吧
    2018-05-05
  • vxe-table如何在单元格中渲染简单的饼图

    vxe-table如何在单元格中渲染简单的饼图

    这篇文章主要介绍了vxe-table如何在单元格中渲染简单的饼图,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • element-ui自定义表格如何给input双向绑定数据

    element-ui自定义表格如何给input双向绑定数据

    这篇文章主要介绍了element-ui自定义表格如何给input双向绑定数据,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • vue项目中的组件传值方式

    vue项目中的组件传值方式

    这篇文章主要介绍了vue项目中的组件传值方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06

最新评论