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内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Vue3发送post请求出现400 Bad Request报错的解决办法
这篇文章主要给大家介绍了关于Vue3发送post请求出现400 Bad Request报错的解决办法,文中通过实例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下2023-02-02解决el-cascader在IE11浏览器中加载页面自动展开下拉框问题
这篇文章主要为大家介绍了解决el-cascader在IE11浏览器中加载页面自动展开下拉框问题,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2023-06-06Vue 父子组件数据传递的四种方式( inheritAttrs + $attrs + $listeners)
这篇文章主要介绍了Vue 父子组件数据传递的四种方式( inheritAttrs + $attrs + $listeners),需要的朋友可以参考下2018-05-05
最新评论