vuex刷新頁面丟失登錄token信息的解決方案
最近真的是和這個(gè)token給干上了,被這個(gè)token驗(yàn)證搞的非常無語了
先記錄幾個(gè)問題:
- 后端設(shè)置了token的有效期,前端也設(shè)置了請(qǐng)求攔截和響應(yīng)攔截,響應(yīng)攔截中也對(duì)狀態(tài)碼為401的token返回錯(cuò)誤狀態(tài)碼進(jìn)行了token清除,但是localstorage中一直沒有清除token,還是可以保持登錄,讓人抓狂;
- 每次刷新頁面,就會(huì)丟失登錄用戶的信息,讓人抓狂+1;
- 每次關(guān)閉頁面,再重新進(jìn)入頁面,用戶登錄信息再次丟失,抓狂,,,;
抓狂了一整天,還是解決了,貌似解決了,記錄一下
前后端生成使用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("用戶名或密碼錯(cuò)誤"); ? ? 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, ? ? }); ? }); };
前端登錄的時(shí)候用把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('登錄失敗,請(qǐng)檢查用戶名及密碼是否正確!') ? ? ? ? ? ? ? ? ? ? ? ? }) ? ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? ? ? this.$message({ ? ? ? ? ? ? ? ? ? ? ? ? type: "error", ? ? ? ? ? ? ? ? ? ? ? ? message: '錯(cuò)誤提交申請(qǐng)' ? ? ? ? ? ? ? ? ? ? ? ? }) ? ? ? ? ? ? ? ? ? ? return false ? ? ? ? ? ? ? ? } ? ? ? ? ? ? }) ? ? ? ? },
邏輯就是,后端生成了一個(gè)token,并設(shè)定了token的有效期,然后前端請(qǐng)求接口時(shí),獲取到這個(gè)token,并將這個(gè)token命名為mytoken存到本地,并將解碼后的token存放到vuex的state.user中(this.$store.dispatch("setUser", decode))??湛跓o憑,我放一下我的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的過期刪除使用
正常的邏輯是對(duì)axios進(jìn)行二次封裝,在請(qǐng)求攔截和響應(yīng)攔截中對(duì)token進(jìn)行處理,正常的邏輯代碼如下:
import axios from "axios"; import { Message, Loading } from 'element-ui'; import router from "./router" // 請(qǐng)求攔截 axios.interceptors.request.use(config => { ? ? if(localStorage.eleToken){ ? ? ? ? // 設(shè)置統(tǒng)一的請(qǐng)求頭 ? ? ? ? config.headers.Authorization = localStorage.eleToken ? ? } ? ? return config }, error => { ? ? return Promise.reject(error) }) //響應(yīng)攔截 axios.interceptors.response.use(response => { ? ? return response }, error => { ? ? // 錯(cuò)誤提醒 ? ? endLoading(); ? ? Message.error(error.response.data) ? ? // 獲取錯(cuò)誤狀態(tài)碼 ? ? const {status} = error.response ? ? if(status == 401){ ? ? ? ? Message.error("token失效,請(qǐng)重新登錄") ? ? ? ? localStorage.removeItem('eleToken') ? ? ? ? router.push('/login') ? ? } ? ? return Promise.reject(error) }) export default axios
邏輯不解釋了,就是請(qǐng)求頭設(shè)置驗(yàn)證,響應(yīng)時(shí)發(fā)現(xiàn)狀態(tài)碼為401就表示token過期了應(yīng)該刪除,可是讓我抓狂的時(shí),設(shè)置了10s的過期時(shí)間,頁面還是一直保持著登錄狀態(tài),,面向百度和CSDN編程了大半天沒發(fā)現(xiàn)錯(cuò)在哪里,于是放棄了用這個(gè)方案。
解決方法:
其實(shí)已經(jīng)在我上一篇博客中提到了,我今天又完善了一下,記錄一下代碼:
// 路由守衛(wèi) 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文件中
可以看出,我并沒有另外再設(shè)置過期時(shí)間,而是根據(jù)后端返回的token的創(chuàng)建時(shí)間(decode.iat)和到期時(shí)間(decode.exp)的差與當(dāng)前時(shí)間(date)和創(chuàng)建時(shí)間之差進(jìn)行比較,這樣更科學(xué)
好了,第一個(gè)問題解決了,進(jìn)入下一個(gè)問題。
vuex刷新頁面丟失登錄信息
這個(gè)問題非常好解釋,因?yàn)槲业挠脩粜畔⒋鎯?chǔ)在store中(也就是vuex中),每次刷新頁面的時(shí)候,store的數(shù)據(jù)就會(huì)被釋放,所以就丟失了用戶信息,怎么處理呢,每次重載頁面的時(shí)候,將用戶信息寫在頁面的sessionstorage中,代碼如下:
created() { // 在頁面加載時(shí)讀取sessionStorage里的狀態(tài)信息 if (sessionStorage.getItem('store')) { this.$store.replaceState( Object.assign( {}, this.$store.state, JSON.parse(sessionStorage.getItem('store')) ) ) } // 在頁面刷新時(shí)將vuex里的信息保存到sessionStorage里,beforeunload事件在頁面刷新時(shí)先觸發(fā) window.addEventListener('beforeunload', () => { sessionStorage.setItem('store', JSON.stringify(this.$store.state)) }) // console.log(this.$store.state) }
代碼寫在主組件App.vue中,邏輯也很好解釋,就是每次刷新頁面之前,將vuex里的信息保存到sessionStorage里,具體方法是設(shè)置一個(gè)名為store的item存進(jìn)去,然后每次重新加載頁面的時(shí)候,只要發(fā)現(xiàn)頁面的sessionStorage中存了’store’,就將已經(jīng)釋放掉了的store數(shù)據(jù)(注意,這個(gè)不是剛才命名的store)中寫入這個(gè)sessionStorage中存的’store’,這樣,每次刷新頁面,都會(huì)重新把數(shù)據(jù)寫到store中,算是解決問題了
但是,有個(gè)問題是,只要一關(guān)閉頁面,sessionstorage中的數(shù)據(jù)就沒有了,,,
也就是說,關(guān)閉頁面后,再打開頁面,localstorage中有token,可以避開設(shè)置好的路由守衛(wèi)進(jìn)入頁面,但是卻沒有用戶信息,頁面上有需要顯示用戶信息的,或者需要用戶權(quán)限的功能全部沒有了,真是操蛋,,
因此進(jìn)入下一個(gè)問題
vuex關(guān)閉頁面丟失登錄信息的解決方案
我直接上代碼吧
?created() { ? ? // 在頁面加載時(shí)讀取sessionStorage里的狀態(tài)信息 ? ? // if (sessionStorage.getItem('store')) { ? ? // ? this.$store.replaceState( ? ? // ? ? Object.assign( ? ? // ? ? ? {}, ? ? // ? ? ? this.$store.state, ? ? // ? ? ? JSON.parse(sessionStorage.getItem('store')) ? ? // ? ? ) ? ? // ? ) ? ? // } ? ? // // 在頁面刷新時(shí)將vuex里的信息保存到sessionStorage里,beforeunload事件在頁面刷新時(shí)先觸發(fā) ? ? ? ? // 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中,看到?jīng)],我把sessionstorage相關(guān)的代碼全部注釋起來了
然后實(shí)際上就是把localstorage中的mytoken解析出來,然后傳遞給store中的user,就這樣,每次加載頁面的時(shí)候,總能保證store中是有用戶信息的,除非token失效。
大功告成,就是不知道明天上班會(huì)報(bào)什么稀奇古怪的錯(cuò)來,,,
到此這篇關(guān)于vuex刷新頁面丟失登錄token信息的解決方案的文章就介紹到這了,更多相關(guān)vuex刷新頁面丟失token內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- vue中雙token和無感刷新token的區(qū)別
- Vue實(shí)現(xiàn)雙token無感刷新的示例代碼
- vue2實(shí)現(xiàn)無感刷新token的方式詳解
- VUE前端實(shí)現(xiàn)token的無感刷新方式
- Vue項(xiàng)目實(shí)現(xiàn)token無感刷新的示例代碼
- 前端使用vue實(shí)現(xiàn)token無感刷新的三種方案解析
- Vue3+Vite使用雙token實(shí)現(xiàn)無感刷新
- 關(guān)于Vue 消除Token過期時(shí)刷新頁面的重復(fù)提示問題
- vue的token刷新處理的方法
- Vue項(xiàng)目中實(shí)現(xiàn)無感Token刷新的示例
相關(guān)文章
vue3中的對(duì)象時(shí)為proxy對(duì)象如何獲取值(兩種方式)
使用vue3.0時(shí),因?yàn)榈讓邮鞘褂胮roxy進(jìn)行代理的所以當(dāng)我們打印一些值得時(shí)候是proxy代理之后的是Proxy<BR>對(duì)象,Proxy對(duì)象里邊的[[Target]]才是真實(shí)的對(duì)象,那么如何獲取這個(gè)值呢,下面下面給大家介紹兩種方式,感興趣的朋友一起看看吧2023-01-01關(guān)于配置babel-plugin-import報(bào)錯(cuò)的坑及解決
這篇文章主要介紹了關(guān)于配置babel-plugin-import報(bào)錯(cuò)的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12vue項(xiàng)目實(shí)現(xiàn)m3u8流媒體播放詳細(xì)圖文教程
m3u8是一種常用的視頻流媒體格式,通常用于在Web上播放視頻,這篇文章主要給大家介紹了關(guān)于vue項(xiàng)目實(shí)現(xiàn)m3u8流媒體播放的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-09-09Vue項(xiàng)目判斷開發(fā)、測(cè)試、正式環(huán)境過程
這篇文章主要介紹了Vue項(xiàng)目判斷開發(fā)、測(cè)試、正式環(huán)境過程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04