vuex刷新页面丢失登录token信息的解决方案

 更新时间:2023年07月31日 09:26:40   作者:栀椩  
本文主要介绍了vuex刷新页面丢失登录token信息的解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

最近真的是和这个token给干上了,被这个token验证搞的非常无语了

先记录几个问题:

  • 后端设置了token的有效期,前端也设置了请求拦截和响应拦截,响应拦截中也对状态码为401的token返回错误状态码进行了token清除,但是localstorage中一直没有清除token,还是可以保持登录,让人抓狂;
  • 每次刷新页面,就会丢失登录用户的信息,让人抓狂+1;
  • 每次关闭页面,再重新进入页面,用户登录信息再次丢失,抓狂,,,;

抓狂了一整天,还是解决了,貌似解决了,记录一下

前后端生成使用token的流程

后端怎么写token,前端怎么用token,我不想再说了,前面两篇博客都写了,我直接上代码

后端生成token的代码:

// 登录
exports.login = (req, res) => {
  const userinfo = req.body;
  //   console.log(userinfo)
  const sql = "select * from users where username = ?";
  db.query(sql, userinfo.username, (err, results) => {
    if (err) return res.status(404).json(err);
    if (results.length !== 1) return res.status(400).json("用户不存在");
    const compareResult = bcrypt.compareSync(
      userinfo.password,
      results[0].password
    );
    if (!compareResult) return res.status(400).json("用户名或密码错误");
    const user = {
      id: results[0].id,
      username: results[0].username,
      email: results[0].email,
      identify: results[0].identify
    };
    const tokenStr = jwt.sign(user, config.jwtSecretKey, { expiresIn: 36000 });
    // if (jwt.verify(tokenStr, config.jwtSecretKey, (err, decode) => {
    //   if (err) return res.status(401).json(err)
    // }))
    res.json({
      status: 200,
      message: "登录成功",
      token: "Bearer " + tokenStr,
    });
  });
};

前端登录的时候用把token写到localstorage中:

submitForm(formName) {
            this.$refs[formName].validate(valid => {
                if (valid) {
                    this.$axios.post('/user/login', this.loginUser)
                        .then(res => {
                            const { token } = res.data
                            // console.log(token)
                            localStorage.setItem('mytoken', token)
                            // 解析token
                            const decode = jwt_decode(token)
                            console.log(decode)
                            // 将解析后的token存入vuex中
                            this.$store.dispatch('setAuthenticated', !this.isEmpty(decode))
                            this.$store.dispatch("setUser", decode)
                            this.$router.push('/')
                        })
                        .catch(err => {
                            // console.log(err)
                            this.$message.error('登录失败,请检查用户名及密码是否正确!')
                        })
                } else {
                    this.$message({
                        type: "error",
                        message: '错误提交申请'    
                    })
                    return false
                }
            })
        },

逻辑就是,后端生成了一个token,并设定了token的有效期,然后前端请求接口时,获取到这个token,并将这个token命名为mytoken存到本地,并将解码后的token存放到vuex的state.user中(this.$store.dispatch("setUser", decode))。空口无凭,我放一下我的store/index.js文件中的setUser

const actions = {
  setAuthenticated: ({ commit }, isAuthenticated) => {
    commit(types.SET_AUTHENTICATED, isAuthenticated);
  },
  setUser: ({ commit }, user) => {
    commit(types.SET_USER, user);
  },
  clearCurrentState: ({ commit }) => {
    commit(types.SET_AUTHENTICATED, false);
    commit(types.SET_USER, null);
  },
};

好了,token放在localstorage中了,至于要不要将token存放到vuex的state.user中,不影响token的过期删除使用

正常的逻辑是对axios进行二次封装,在请求拦截和响应拦截中对token进行处理,正常的逻辑代码如下:

import axios from "axios";
import { Message, Loading } from 'element-ui';
import router from "./router"
// 请求拦截
axios.interceptors.request.use(config => {
    if(localStorage.eleToken){
        // 设置统一的请求头
        config.headers.Authorization = localStorage.eleToken
    }
    return config
}, error => {
    return Promise.reject(error)
})
//响应拦截
axios.interceptors.response.use(response => {
    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

逻辑不解释了,就是请求头设置验证,响应时发现状态码为401就表示token过期了应该删除,可是让我抓狂的时,设置了10s的过期时间,页面还是一直保持着登录状态,,面向百度和CSDN编程了大半天没发现错在哪里,于是放弃了用这个方案。

解决方法:

其实已经在我上一篇博客中提到了,我今天又完善了一下,记录一下代码:

// 路由守卫
import jwt_decode from 'jwt-decode'
router.beforeEach((to, from, next) => {
  // const EXPIRESTIME = 36000  
  const isLogin = localStorage.mytoken ? true : false;
  if (isLogin){
    const decode = jwt_decode(localStorage.mytoken)
    const date = parseInt(new Date().getTime() / 1000)
    if ((date - decode.iat) > (decode.exp - decode.iat)){
      localStorage.removeItem('mytoken')
      next("/login");
    }
  }
  if (to.path == "/login" || to.path == "/register") {
    next();
  } else {
    isLogin ? next() : next("/login");
  }
});

上面这段代码写在我的路由处理文件router/index.js文件中

可以看出,我并没有另外再设置过期时间,而是根据后端返回的token的创建时间(decode.iat)和到期时间(decode.exp)的差与当前时间(date)和创建时间之差进行比较,这样更科学

好了,第一个问题解决了,进入下一个问题。

vuex刷新页面丢失登录信息

这个问题非常好解释,因为我的用户信息存储在store中(也就是vuex中),每次刷新页面的时候,store的数据就会被释放,所以就丢失了用户信息,怎么处理呢,每次重载页面的时候,将用户信息写在页面的sessionstorage中,代码如下:

created() {
    // 在页面加载时读取sessionStorage里的状态信息
   if (sessionStorage.getItem('store')) {
       this.$store.replaceState(
         Object.assign(
           {},
           this.$store.state,
           JSON.parse(sessionStorage.getItem('store'))
         )
      )
     }
     // 在页面刷新时将vuex里的信息保存到sessionStorage里,beforeunload事件在页面刷新时先触发    
     window.addEventListener('beforeunload', () => {
       sessionStorage.setItem('store', JSON.stringify(this.$store.state))      
     })
    // console.log(this.$store.state)
}

代码写在主组件App.vue中,逻辑也很好解释,就是每次刷新页面之前,将vuex里的信息保存到sessionStorage里,具体方法是设置一个名为store的item存进去,然后每次重新加载页面的时候,只要发现页面的sessionStorage中存了’store’,就将已经释放掉了的store数据(注意,这个不是刚才命名的store)中写入这个sessionStorage中存的’store’,这样,每次刷新页面,都会重新把数据写到store中,算是解决问题了

但是,有个问题是,只要一关闭页面,sessionstorage中的数据就没有了,,,

也就是说,关闭页面后,再打开页面,localstorage中有token,可以避开设置好的路由守卫进入页面,但是却没有用户信息,页面上有需要显示用户信息的,或者需要用户权限的功能全部没有了,真是操蛋,,

因此进入下一个问题

vuex关闭页面丢失登录信息的解决方案

我直接上代码吧

 created() {
    // 在页面加载时读取sessionStorage里的状态信息
    // if (sessionStorage.getItem('store')) {
    //   this.$store.replaceState(
    //     Object.assign(
    //       {},
    //       this.$store.state,
    //       JSON.parse(sessionStorage.getItem('store'))
    //     )
    //   )
    // }
    // // 在页面刷新时将vuex里的信息保存到sessionStorage里,beforeunload事件在页面刷新时先触发    
    // window.addEventListener('beforeunload', () => {
    //   sessionStorage.setItem('store', JSON.stringify(this.$store.state))      
    // })
    // console.log(this.$store.state)
    if (localStorage.getItem('mytoken')) {
      const decode = jwt_decode(localStorage.mytoken)
      // console.log(decode)
      this.$store.dispatch("setUser", decode)
      // this.$store.replaceState(Object.assign({}, this.$store.state, JSON.parse(decode)))
    }
    // window.addEventListener('beforeunload', () => {
    //   localStorage.setItem('mytoken', localStorage.mytoken)
    // })
  },

依然写在App.vue中,看到没,我把sessionstorage相关的代码全部注释起来了

然后实际上就是把localstorage中的mytoken解析出来,然后传递给store中的user,就这样,每次加载页面的时候,总能保证store中是有用户信息的,除非token失效。

大功告成,就是不知道明天上班会报什么稀奇古怪的错来,,,

到此这篇关于vuex刷新页面丢失登录token信息的解决方案的文章就介绍到这了,更多相关vuex刷新页面丢失token内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解vue表单验证组件 v-verify-plugin

    详解vue表单验证组件 v-verify-plugin

    本篇文章主要介绍了详解vue表单验证组件 v-verify-plugin,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-04-04
  • vue props 一次传多个值实例

    vue props 一次传多个值实例

    这篇文章主要介绍了vue props 一次传多个值实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-07-07
  • vue 绑定对象,数组之数据无法动态渲染案例详解

    vue 绑定对象,数组之数据无法动态渲染案例详解

    这篇文章主要介绍了vue 绑定对象,数组之数据无法动态渲染案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-09-09
  • vue插槽slot的简单理解与用法实例分析

    vue插槽slot的简单理解与用法实例分析

    这篇文章主要介绍了vue插槽slot的简单理解与用法,结合实例形式分析了vue插槽slot的功能、原理、相关使用技巧与操作注意事项,需要的朋友可以参考下
    2020-03-03
  • 3分钟迅速学会Vue中methods方法使用技巧

    3分钟迅速学会Vue中methods方法使用技巧

    最近在学习Vue,感觉methods还是有必有总结一下的,下面这篇文章主要给大家介绍了关于3分钟迅速学会Vue中methods方法使用技巧的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-02-02
  • Vue中关于this指向的问题示例详解

    Vue中关于this指向的问题示例详解

    在Vue中,方法体里用this调用vue实例的数据,有时会指向window,导致调用失败报错,这篇文章主要介绍了Vue中关于this指向的问题 ,需要的朋友可以参考下
    2022-07-07
  • Vue-cli框架实现计时器应用

    Vue-cli框架实现计时器应用

    这篇文章主要为大家详细介绍了Vue-cli框架实现计时器应用,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • 关于vue-router路径计算问题

    关于vue-router路径计算问题

    这篇文章主要介绍了关于vue-router路径计算问题,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • 一篇文章搞懂Vue3中如何使用ref获取元素节点

    一篇文章搞懂Vue3中如何使用ref获取元素节点

    过去在Vue2中,我们采用ref来获取标签的信息,用以替代传统 js 中的 DOM 行为,下面这篇文章主要给大家介绍了关于如何通过一篇文章搞懂Vue3中如何使用ref获取元素节点的相关资料,需要的朋友可以参考下
    2022-11-11
  • 关于vuex的数据持久化处理方式

    关于vuex的数据持久化处理方式

    这篇文章主要介绍了关于vuex的数据持久化处理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-10-10

最新评论