• 通过vuex存储token,通过前置路由守卫完成对登录操作之后的token值验证,完成登录状态的保持


    通过vuex存储token,通过前置路由守卫完成对登录操作之后的token值验证,完成登录状态的保持

    在这里插入图片描述

    • 账号和密码正确,则需要来保持用户的登录状态而前后端分离如何保存登录状态
    • 保持用户的登录状态 cookie/session [考虑到跨域问题]
    • 前后端分离保持用户登录状态的方案 token
    • token是后端返回给前端一个加密后的字符串,需要在本地进行保存
    • token存储在vuex中,对于vuex中需要持久化的内容可以存储在本地浏览器中

    一、除过登录路由,在其他路由跳转之时判断token值是否存在。

    全局前置路由守卫

    每次路由跳转之前触发:
    一般可以通过元信息来判断,哪些路由可以不登录就可以访问,那些路由需要这个token才能访问,当然也可以用地址

    router.beforeEach((to,from,next)=>{
        console.log("to",to.meta);
        console.log("from",from);
        if(to.path != '/login'){
             next({
                path: '/admin/staff',
                replace: true
            })
        }else{
            next()
        }
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    通过在路由中添加met元信息来判断访问那些路由需要登录之后(有token值)才能验证访问,

    router.beforeEach((to,from,next)=>{
        console.log("to",to.meta);
        console.log("from",from);
        if(to.meta.istoken){
             next({
                path: '/',
                replace: true
            })
        }else{
            next()
        }
       
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    那么如何去存储这个token值呢。

    对token不了解的话可以看这篇token描述已经应用场景
    首先能想到的是在这个全局的登录之后各个页面(大部分)是需要这个鉴权验证,也就是对当前用户的判定,也就是生成一个唯一的token值,在后面的每次http访问都带上:

    • 那我们这能想到的是除了登陆请求,在请求拦截器中对所有的请求添加 token 请求字段
    import axios from 'axios'
    const instance = axios.create()
    //把get暂时存在sessionStoring中
    //给请求头添加token。
    instance.interceptors.request.use(config => {
      config.url != '/api/login' ? (config.headers.token = store.getters.token) : null
      return config
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    这里通过express框架,搭建一个简易服务器,针对一路由请求对token是否存在的进行判断,

    let allows = [
        '/api/login',
        '/api/upfile'
    ]
    module.exports = (req, res, next) => {
        let token = req.headers.token || ''
        if (!allows.includes(req.path)) {
            if (token == '') {
                res.send({
                    code: 1000,
                    msg: 'token无效',
                    data: null
                })
                return;
            }
            // 如果token存在,进行解密,得到明文
            // 明文中一般会有账号和对应的用户id信息,用此信息在数据表中去查询,如果存在,则返回数据,不存在返回,没有授权
            next()
        }
        next()
    }
    *******************************************
    const checkToken = require('./middleware')
    app.use(checkToken);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    考虑到:那这个token其实需要在全局的的组中都需要用到,就把它放在vuex中,
    并想到数据持久化。
    在给vuex传入的同时,进行本地存储;

    import {
        doLoginApi
    } from '@/api/userApi'
    import Store from '@/utils/store'
    import {
        hasToken
    } from '@/utils/token'
    const sessionStore = new Store()
    
    export default {
        state: {
            token: '',
            nickname: ''
        },
        mutations: {
            // 写入vuex的同时,进行本地存储,为了持久化
            setUserLoginInfo(state, payload) {
                state.token = payload.token
                state.nickname = payload.nickname;
                !hasToken() && setStorage(payload)
            },
            userLogout(state, payload) {
                state.token = ''
                state.nickname = ''
                sessionStore.remove('token')
                sessionStore.remove('nickname')
                window.location.href = '/login'
            }
        },
        actions: {
            // 进行网络请求的调用,验证账号和密码是否正确
            async fetchUserLogin({
                commit
            }, payload) {
                let ret = await doLoginApi(payload)
                // 通知vuex中的state来修改对应的token数据
                commit('setUserLoginInfo', ret.data)
                return ret.code
            }
        }
    }
    
    
    function setStorage({
        token,
        nickname
    }) {
        sessionStore.set('token', token)
        sessionStore.set('nickname', nickname)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    针对本地存储封装成一个类导出:

    class Store {
        // attrname 它是 sessionStorage 还是  localStorage
        // constructor(attrName = 'sessionStorage') {
        // session / local
        constructor(attrName = 'session') {
            this.attrName = attrName + 'Storage'
        }
        set(key, value) {
            if (typeof value == 'object') {
                value = JSON.stringify(value)
            }
            // sessionStorage.setItem(key, value)
            window[this.attrName].setItem(key, value)
        }
    
        get(key, defaultValue = '') {
            let value = window[this.attrName].getItem(key)
            value = value ? value : defaultValue
            value = /[\[\{]/.test(value) ? JSON.parse(value) : value
            return value
        }
    
        remove(key) {
            window[this.attrName].removeItem(key)
        }
    }
    
    // export default new Store()
    export default Store
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
  • 相关阅读:
    【零基础学Java】第二十篇 包装类3(Math,Arrays,System,BigInteger,BigDecimal,日期)
    27、Flink 的SQL之SELECT (SQL Hints 和 Joins)介绍及详细示例(2-2)
    智能安防系统-视频监控系统
    10、IOC 之类路径扫描和托管组件
    图片隐写,盲水印,加密logo
    平行坐标图:高维数据可视化必备图形
    关于GP7 release版在麒麟V10信创操作系统编译不过的问题解决
    小红书种草步骤:小红书种草怎么做?
    Spring的Bean生命周期+bean注入+项目启动时正确姿势初始化数据的五种方式
    java基于ssm的奖学金管理系统-计算机毕业设计
  • 原文地址:https://blog.csdn.net/m0_46672781/article/details/126841926