vuex刷新頁面丟失登錄token信息的解決方案
最近真的是和這個token給干上了,被這個token驗證搞的非常無語了
先記錄幾個問題:
- 后端設(shè)置了token的有效期,前端也設(shè)置了請求攔截和響應(yīng)攔截,響應(yīng)攔截中也對狀態(tài)碼為401的token返回錯誤狀態(tài)碼進(jìn)行了token清除,但是localstorage中一直沒有清除token,還是可以保持登錄,讓人抓狂;
- 每次刷新頁面,就會丟失登錄用戶的信息,讓人抓狂+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("用戶名或密碼錯誤");
? ? 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,并設(shè)定了token的有效期,然后前端請求接口時,獲取到這個token,并將這個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的過期刪除使用
正常的邏輯是對axios進(jìn)行二次封裝,在請求攔截和響應(yīng)攔截中對token進(jìn)行處理,正常的邏輯代碼如下:
import axios from "axios";
import { Message, Loading } from 'element-ui';
import router from "./router"
// 請求攔截
axios.interceptors.request.use(config => {
? ? if(localStorage.eleToken){
? ? ? ? // 設(shè)置統(tǒng)一的請求頭
? ? ? ? config.headers.Authorization = localStorage.eleToken
? ? }
? ? return config
}, error => {
? ? return Promise.reject(error)
})
//響應(yīng)攔截
axios.interceptors.response.use(response => {
? ? return response
}, error => {
? ? // 錯誤提醒
? ? endLoading();
? ? Message.error(error.response.data)
? ? // 獲取錯誤狀態(tài)碼
? ? const {status} = error.response
? ? if(status == 401){
? ? ? ? Message.error("token失效,請重新登錄")
? ? ? ? localStorage.removeItem('eleToken')
? ? ? ? router.push('/login')
? ? }
? ? return Promise.reject(error)
})
export default axios邏輯不解釋了,就是請求頭設(shè)置驗證,響應(yīng)時發(fā)現(xiàn)狀態(tài)碼為401就表示token過期了應(yīng)該刪除,可是讓我抓狂的時,設(shè)置了10s的過期時間,頁面還是一直保持著登錄狀態(tài),,面向百度和CSDN編程了大半天沒發(fā)現(xiàn)錯在哪里,于是放棄了用這個方案。
解決方法:
其實已經(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è)置過期時間,而是根據(jù)后端返回的token的創(chuàng)建時間(decode.iat)和到期時間(decode.exp)的差與當(dāng)前時間(date)和創(chuàng)建時間之差進(jìn)行比較,這樣更科學(xué)
好了,第一個問題解決了,進(jìn)入下一個問題。
vuex刷新頁面丟失登錄信息
這個問題非常好解釋,因為我的用戶信息存儲在store中(也就是vuex中),每次刷新頁面的時候,store的數(shù)據(jù)就會被釋放,所以就丟失了用戶信息,怎么處理呢,每次重載頁面的時候,將用戶信息寫在頁面的sessionstorage中,代碼如下:
created() {
// 在頁面加載時讀取sessionStorage里的狀態(tài)信息
if (sessionStorage.getItem('store')) {
this.$store.replaceState(
Object.assign(
{},
this.$store.state,
JSON.parse(sessionStorage.getItem('store'))
)
)
}
// 在頁面刷新時將vuex里的信息保存到sessionStorage里,beforeunload事件在頁面刷新時先觸發(fā)
window.addEventListener('beforeunload', () => {
sessionStorage.setItem('store', JSON.stringify(this.$store.state))
})
// console.log(this.$store.state)
}代碼寫在主組件App.vue中,邏輯也很好解釋,就是每次刷新頁面之前,將vuex里的信息保存到sessionStorage里,具體方法是設(shè)置一個名為store的item存進(jìn)去,然后每次重新加載頁面的時候,只要發(fā)現(xiàn)頁面的sessionStorage中存了’store’,就將已經(jīng)釋放掉了的store數(shù)據(jù)(注意,這個不是剛才命名的store)中寫入這個sessionStorage中存的’store’,這樣,每次刷新頁面,都會重新把數(shù)據(jù)寫到store中,算是解決問題了
但是,有個問題是,只要一關(guān)閉頁面,sessionstorage中的數(shù)據(jù)就沒有了,,,
也就是說,關(guān)閉頁面后,再打開頁面,localstorage中有token,可以避開設(shè)置好的路由守衛(wèi)進(jìn)入頁面,但是卻沒有用戶信息,頁面上有需要顯示用戶信息的,或者需要用戶權(quán)限的功能全部沒有了,真是操蛋,,
因此進(jìn)入下一個問題
vuex關(guān)閉頁面丟失登錄信息的解決方案
我直接上代碼吧
?created() {
? ? // 在頁面加載時讀取sessionStorage里的狀態(tài)信息
? ? // if (sessionStorage.getItem('store')) {
? ? // ? this.$store.replaceState(
? ? // ? ? Object.assign(
? ? // ? ? ? {},
? ? // ? ? ? this.$store.state,
? ? // ? ? ? JSON.parse(sessionStorage.getItem('store'))
? ? // ? ? )
? ? // ? )
? ? // }
? ? // // 在頁面刷新時將vuex里的信息保存到sessionStorage里,beforeunload事件在頁面刷新時先觸發(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)的代碼全部注釋起來了
然后實際上就是把localstorage中的mytoken解析出來,然后傳遞給store中的user,就這樣,每次加載頁面的時候,總能保證store中是有用戶信息的,除非token失效。
大功告成,就是不知道明天上班會報什么稀奇古怪的錯來,,,
到此這篇關(guān)于vuex刷新頁面丟失登錄token信息的解決方案的文章就介紹到這了,更多相關(guān)vuex刷新頁面丟失token內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在使用vue-cli創(chuàng)建vue項目,如何添加和刪除預(yù)置配置
這篇文章主要介紹了在使用vue-cli創(chuàng)建vue項目,如何添加和刪除預(yù)置配置問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10
vue2和el-input無法修改和寫入并且不報錯的解決方案
這篇文章主要介紹了vue2和el-input無法修改和寫入并且不報錯的解決方案,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2024-07-07
Vue.js?的計算屬性和偵聽器詳解(提升數(shù)據(jù)處理與交互的關(guān)鍵工具)
在Vue.js開發(fā)中,計算屬性與偵聽器是極為關(guān)鍵的特性,它們極大地提升了數(shù)據(jù)處理與交互邏輯實現(xiàn)的便捷性和高效性,本文給大家介紹Vue.js?的計算屬性和偵聽器:提升數(shù)據(jù)處理與交互的關(guān)鍵工具,感興趣的朋友一起看看吧2025-04-04

