前端檢測(cè)用戶登錄狀態(tài)是否過期的幾種方法
在前端開發(fā)中 , 判斷用戶登錄狀態(tài)是否過期是一個(gè)常見的需求。尤其是在復(fù)雜的場(chǎng)景中 , 準(zhǔn)確判斷用戶登錄狀態(tài)是否過期是保障用戶體驗(yàn)的關(guān)鍵環(huán)節(jié)。這一過程涉及到服務(wù)器與前端之間的緊密協(xié)作 , 以及多種技術(shù)手段的綜合運(yùn)用 , 還是蠻有挑戰(zhàn)性的。
判斷登錄過期的主要方法有: 檢查令牌有效期 , 定時(shí)輪詢服務(wù)器 , 全局請(qǐng)求攔截器 , 利用web存儲(chǔ)中的時(shí)間戳。
一、檢查令牌有效期
對(duì)于包含有效期信息的令牌(如 JWT 中的exp字段),前端可以在每次發(fā)送請(qǐng)求之前對(duì)令牌進(jìn)行檢查。以下是一個(gè)簡(jiǎn)單的檢查 JWT 令牌有效期的函數(shù)示例(使用jwt-decode庫(kù)來解析 JWT):
import jwt_decode from 'jwt-decode'; function checkTokenValidity(token) { try { const decodedToken = jwt_decode(token); const currentTime = Date.now() / 1000; // 獲取當(dāng)前時(shí)間(以秒為單位) if (decodedToken.exp < currentTime) { console.log('令牌已過期(令牌有效期檢查)'); return false; } return true; } catch (error) { console.log('令牌解析出錯(cuò):', error); return false; } } // 在發(fā)送請(qǐng)求前調(diào)用此函數(shù)檢查令牌 const token = localStorage.getItem('token'); if (checkTokenValidity(token)) { // 令牌有效,繼續(xù)發(fā)送請(qǐng)求 // 這里假設(shè)使用`axios`發(fā)送請(qǐng)求 axios.get('/api/data'); } else { console.log('登錄狀態(tài)可能已過期,需處理'); // 處理登錄過期情況,如提示用戶重新登錄 }
二、定時(shí)輪詢服務(wù)器
輪詢服務(wù)器狀態(tài)是一種主動(dòng)檢查令牌是否有效的方法。前端可以定期發(fā)送請(qǐng)求到服務(wù)器,檢查令牌是否仍然有效。
1. 定時(shí)輪詢
設(shè)置一個(gè)定時(shí)器,每隔一定時(shí)間發(fā)送請(qǐng)求到服務(wù)器,檢查令牌狀態(tài):
function checkTokenStatus() { axios.get('/auth/check') .then(response => { if (!response.data.valid) { // 令牌無效,執(zhí)行登出邏輯 logout(); } }) .catch(error => { // 網(wǎng)絡(luò)錯(cuò)誤或其他問題,執(zhí)行登出邏輯 logout(); }); } setInterval(checkTokenStatus, 15 * 60 * 1000); // 每15分鐘檢查一次
2.優(yōu)化輪詢頻率
需求背景: 在企業(yè)級(jí)應(yīng)用中,可能會(huì)有大量用戶同時(shí)在線,頻繁的過期檢測(cè)操作(如定時(shí)輪詢)會(huì)對(duì)系統(tǒng)性能造成過大的負(fù)擔(dān)。因此,需要采用高效的過期檢測(cè)機(jī)制,例如優(yōu)化輪詢的頻率,或者采用更智能的令牌有效期檢查算法,減少不必要的檢測(cè)次數(shù)。
為了減少對(duì)服務(wù)器的壓力,可以根據(jù)用戶的操作頻率調(diào)整輪詢頻率。例如,在用戶活躍時(shí)頻繁檢查,在用戶長(zhǎng)時(shí)間沒有操作時(shí)減少檢查頻率。
let lastActivityTime = Date.now(); document.addEventListener('mousemove', () => lastActivityTime = Date.now()); document.addEventListener('keydown', () => lastActivityTime = Date.now()); setInterval(() => { if (Date.now() - lastActivityTime < 5 * 60 * 1000) { // 用戶5分鐘內(nèi)有操作 checkTokenStatus(); } }, 15 * 60 * 1000);
這種方法可以在確保安全性的同時(shí)減少對(duì)服務(wù)器的壓力。
三、全局請(qǐng)求攔截器
前端在發(fā)送請(qǐng)求時(shí),可以通過檢查服務(wù)器的響應(yīng)狀態(tài)碼來判斷登錄是否過期。通常,服務(wù)器會(huì)返回401未授權(quán)狀態(tài)碼表示令牌無效或過期。
1. 捕獲401狀態(tài)碼
axios.interceptors.response.use(response => { return response; }, error => { if (error.response.status === 401) { // 令牌無效或過期,執(zhí)行登出邏輯 logout(); } return Promise.reject(error); });
2.彈出登錄提示
當(dāng)捕獲到401狀態(tài)碼時(shí) , 可以彈出登錄提示 , 引導(dǎo)用戶重新登錄:
function logout() { // 清除本地存儲(chǔ)的令牌 removeToken(); // 彈出登錄提示 alert('登錄已過期,請(qǐng)重新登錄'); // 跳轉(zhuǎn)到登錄頁面 window.location.href = '/login'; }
這種方法可以確保前端在令牌過期時(shí)及時(shí)響應(yīng),提高了系統(tǒng)的安全性。
四、利用web中的持久化存儲(chǔ)
前端可以在登錄成功時(shí)將令牌的有效期時(shí)間戳保存到Web存儲(chǔ)(如localStorage或sessionStorage),并在每次請(qǐng)求前檢查時(shí)間戳是否過期。
1.保存時(shí)間戳
在用戶登錄成功后 , 將令牌和有效期時(shí)間戳保存到 localStorage
中:
function saveToken(token, expiresIn) { const expirationTime = Date.now() + expiresIn * 1000; localStorage.setItem('token', token); localStorage.setItem('tokenExpiration', expirationTime); }
2.檢查時(shí)間戳
在每次請(qǐng)求前,檢查當(dāng)前時(shí)間是否超過保存的時(shí)間戳:
function isTokenExpired() { const expirationTime = localStorage.getItem('tokenExpiration'); return Date.now() >= expirationTime; }
如果時(shí)間戳過期,則提示用戶重新登錄:
axios.interceptors.request.use(config => { if (isTokenExpired()) { // 令牌過期,執(zhí)行登出邏輯 logout(); } else { const token = localStorage.getItem('token'); config.headers['Authorization'] = `Bearer ${token}`; } return config; }, error => { return Promise.reject(error); });
特定場(chǎng)景中的優(yōu)化方案
前面都是檢測(cè)用戶登錄狀態(tài)的方法 , 這個(gè)時(shí)候 產(chǎn)品經(jīng)理
提出一個(gè)需要優(yōu)化的點(diǎn):
需求背景: 在業(yè)務(wù)流程中,用戶可能正在進(jìn)行重要的操作(如填寫復(fù)雜的表單、進(jìn)行數(shù)據(jù)分析等)。當(dāng)?shù)卿洜顟B(tài)過期時(shí),應(yīng)盡量避免突然中斷用戶操作,如在不影響用戶當(dāng)前輸入的情況下彈出提示框,引導(dǎo)用戶重新登錄。
那我們?nèi)绾螌?shí)現(xiàn)這個(gè)需求呢? 答案是--------優(yōu)雅降級(jí)
當(dāng)檢測(cè)到登錄狀態(tài)過期時(shí),為了避免給用戶帶來突兀的體驗(yàn),我們需要采用優(yōu)雅降級(jí)的方式。例如,可以通過模態(tài)框提示用戶登錄過期信息,并允許用戶重新登錄,同時(shí)要保留當(dāng)前頁面的狀態(tài)。以下是一個(gè)使用 React.js 實(shí)現(xiàn)的簡(jiǎn)單示例(使用react-bootstrap
的模態(tài)框組件):
首先,確保項(xiàng)目中已經(jīng)安裝了react-bootstrap
和react-router-dom
庫(kù)。
import React, { useState } from 'react'; import { Button, Modal } from 'react-bootstrap'; import { useHistory } from 'react-router-dom'; const LoginExpiredModal = () => { const [dialogVisible, setDialogVisible] = useState(false); const history = useHistory(); // 這里模擬存儲(chǔ)當(dāng)前頁面的一些狀態(tài)信息,比如表單數(shù)據(jù)等 const currentPageState = { formData: { name: 'John', age: 30 } }; const showModal = () => { setDialogVisible(true); }; const handleClose = () => { // 將當(dāng)前頁面狀態(tài)存儲(chǔ)到localStorage中 localStorage.setItem('pageState', JSON.stringify(currentPageState)); // 重定向到登錄頁面 history.push('/login'); }; return ( <div> <Button onClick={showModal}>模擬觸發(fā)登錄過期提示</Button> <Modal show={dialogVisible} onHide={handleClose}> <Modal.Header closeButton> <Modal.Title>登錄過期</Modal.Title> </Modal.Header> <Modal.Body> <p>您的登錄已過期,請(qǐng)重新登錄。</p> </Modal.Body> </Modal> </div> ); }; export default LoginExpiredModal;
總結(jié)
到此這篇關(guān)于前端檢測(cè)用戶登錄狀態(tài)是否過期的文章就介紹到這了,更多相關(guān)前端檢測(cè)用戶登錄狀態(tài)過期內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
一個(gè)不錯(cuò)的js html頁面倒計(jì)時(shí)可精確到秒
這篇文章主要介紹了一個(gè)不錯(cuò)的js html頁面倒計(jì)時(shí)可精確到秒,很簡(jiǎn)單,但和實(shí)用,需要的朋友可以參考下2014-10-10JavaScript實(shí)現(xiàn)數(shù)值自動(dòng)增加動(dòng)畫
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)數(shù)值自動(dòng)增加動(dòng)畫,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12jstl中判斷l(xiāng)ist中是否包含某個(gè)值的簡(jiǎn)單方法
下面小編就為大家?guī)硪黄猨stl中判斷l(xiāng)ist中是否包含某個(gè)值的簡(jiǎn)單方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-10-10flash javascript之間的通訊方法小結(jié)
不用getURL和fsCommand方法個(gè)國(guó)外的通信方法,值得一看2008-12-12javascript eval函數(shù)深入認(rèn)識(shí)
發(fā)現(xiàn)為本文起一個(gè)合適的標(biāo)題還不是那么容易,呵呵,所以在此先說明下本文的兩個(gè)目的2009-02-02