前端身份認(rèn)證與Token安全示例詳解
1. 為什么需要安全的身份認(rèn)證?
隨著 Web 應(yīng)用的普及,用戶登錄和會(huì)話管理成為關(guān)鍵功能。然而,傳統(tǒng)的基于 Session 的認(rèn)證方式存在擴(kuò)展性差、跨域支持不足等問(wèn)題。而基于 Token 的認(rèn)證方式不僅解決了這些問(wèn)題,還能有效提升系統(tǒng)的安全性和性能。
2. 學(xué)習(xí)目標(biāo)
- 理解 JWT 的基本結(jié)構(gòu)及其簽名機(jī)制。
- 掌握如何安全地存儲(chǔ) Token。
- 學(xué)會(huì)設(shè)計(jì)刷新令牌策略,提升用戶體驗(yàn)。
- 結(jié)合實(shí)際代碼示例,在項(xiàng)目中實(shí)現(xiàn)安全的身份認(rèn)證。
JWT 結(jié)構(gòu)詳解
1. 什么是 JWT?
JWT 是一種緊湊、自包含的 Token 格式,用于在客戶端和服務(wù)器之間傳遞聲明(Claims)。它由三部分組成:
- Header:描述 Token 的元信息,如算法類型。
- Payload:存儲(chǔ)用戶信息或聲明。
- Signature:用于驗(yàn)證 Token 的合法性。
示例:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ. SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
2. JWT 的組成部分
(1) Header
定義 Token 的類型和簽名算法。例如:
{
"alg": "HS256",
"typ": "JWT"
}
(2) Payload
存儲(chǔ)用戶信息或聲明。例如:
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
(3) Signature
通過(guò)以下公式生成:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret )
簽名機(jī)制詳解
1. 簽名的作用
簽名確保 Token 的完整性和真實(shí)性,防止篡改和偽造。
2. 常見算法
- HMAC:對(duì)稱加密算法,使用共享密鑰。
- RSA/ECDSA:非對(duì)稱加密算法,使用公鑰和私鑰。
示例(Node.js 實(shí)現(xiàn) HMAC 簽名):
const crypto = require('crypto');
const header = { alg: 'HS256', typ: 'JWT' };
const payload = { sub: '1234567890', name: 'John Doe', iat: 1516239022 };
const secret = 'your-secret-key';
const base64Header = Buffer.from(JSON.stringify(header)).toString('base64');
const base64Payload = Buffer.from(JSON.stringify(payload)).toString('base64');
const signature = crypto
.createHmac('sha256', secret)
.update(`${base64Header}.${base64Payload}`)
.digest('base64');
console.log(`${base64Header}.${base64Payload}.${signature}`);
本地存儲(chǔ)安全
1. 存儲(chǔ)方式對(duì)比
(1)localStorage
優(yōu)點(diǎn):持久化存儲(chǔ),適合長(zhǎng)期保存 Token。
缺點(diǎn):易受 XSS 攻擊。
(2)sessionStorage
優(yōu)點(diǎn):僅在當(dāng)前會(huì)話中有效,關(guān)閉瀏覽器后清除。
缺點(diǎn):同樣易受 XSS 攻擊。
(3)HttpOnly Cookie
優(yōu)點(diǎn):無(wú)法被 JavaScript 訪問(wèn),防御 XSS 攻擊。
缺點(diǎn):需手動(dòng)設(shè)置,且可能受到 CSRF 攻擊。
2. 最佳實(shí)踐
- 將敏感 Token 存儲(chǔ)在
HttpOnly Cookie中。 - 非敏感數(shù)據(jù)(如 UI 狀態(tài))可存儲(chǔ)在
localStorage或sessionStorage中。
刷新令牌策略
1. 為什么需要刷新令牌?
Access Token 通常具有較短的有效期,以降低泄露風(fēng)險(xiǎn)。而 Refresh Token 用于獲取新的 Access Token,從而避免頻繁登錄。
2. 設(shè)計(jì)思路
(1) Access Token
- 有效期短(如 15 分鐘)。
- 存儲(chǔ)在內(nèi)存中,頁(yè)面刷新后失效。
(2) Refresh Token
- 有效期長(zhǎng)(如 7 天)。
- 存儲(chǔ)在
HttpOnly Cookie中,防止 XSS 攻擊。
(3) 刷新流程
- 客戶端檢測(cè) Access Token 是否過(guò)期。
- 如果過(guò)期,向服務(wù)器發(fā)送 Refresh Token 請(qǐng)求新的 Access Token。
- 服務(wù)器驗(yàn)證 Refresh Token 的合法性并返回新的 Access Token。
示例(Node.js 實(shí)現(xiàn)刷新邏輯):
app.post('/refresh-token', (req, res) => {
const refreshToken = req.cookies.refreshToken;
if (!refreshToken || !validateRefreshToken(refreshToken)) {
return res.status(401).send('Invalid refresh token');
}
const newAccessToken = generateAccessToken({ userId: 123 });
res.json({ accessToken: newAccessToken });
});
代碼講解:實(shí)際項(xiàng)目中的實(shí)現(xiàn)
1. Vue 項(xiàng)目中的 JWT 驗(yàn)證
在 Vue 中使用 axios 攔截器處理 Token:
import axios from 'axios';
axios.interceptors.request.use((config) => {
const token = localStorage.getItem('accessToken');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
axios.interceptors.response.use(
(response) => response,
async (error) => {
if (error.response.status === 401) {
const newToken = await refreshToken();
error.config.headers.Authorization = `Bearer ${newToken}`;
return axios(error.config);
}
return Promise.reject(error);
}
);
2. React 項(xiàng)目中的 Token 存儲(chǔ)
在 React 中使用 HttpOnly Cookie 存儲(chǔ) Refresh Token:
// 登錄接口
fetch('/api/login', {
method: 'POST',
body: JSON.stringify({ username, password }),
credentials: 'include'
});
// 刷新 Token 接口
fetch('/api/refresh-token', {
method: 'POST',
credentials: 'include'
});
總結(jié)
1. 核心知識(shí)點(diǎn)回顧
- JWT 的三部分結(jié)構(gòu)及其簽名機(jī)制。
- 不同存儲(chǔ)方式的優(yōu)缺點(diǎn)及最佳實(shí)踐。
- 刷新令牌策略的設(shè)計(jì)與實(shí)現(xiàn)。
2. 實(shí)踐建議
- 使用 HTTPS 保護(hù) Token 傳輸。
- 將敏感 Token 存儲(chǔ)在
HttpOnly Cookie中。 - 定期輪換密鑰,防止密鑰泄露。
到此這篇關(guān)于前端身份認(rèn)證與Token安全的文章就介紹到這了,更多相關(guān)前端身份認(rèn)證與Token安全內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于JS實(shí)現(xiàn)簡(jiǎn)單的隨機(jī)抽取幸運(yùn)員工系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了基于HTML+JavaScript實(shí)現(xiàn)簡(jiǎn)單的隨機(jī)抽取幸運(yùn)員工系統(tǒng),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2023-11-11
javascript 簡(jiǎn)練的幾個(gè)函數(shù)
看CSDN上別人的代碼,感覺比較精煉,拿來(lái)主義,需要的朋友可以看下。2009-08-08
js刪除數(shù)組元素、清空數(shù)組的簡(jiǎn)單方法(必看)
下面小編就為大家?guī)?lái)一篇js刪除數(shù)組元素、清空數(shù)組的簡(jiǎn)單方法(必看)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-07-07
Bootstrap頁(yè)面標(biāo)題Page Header的實(shí)現(xiàn)方法
這篇文章主要為大家詳細(xì)介紹了Bootstrap頁(yè)面標(biāo)題Page Header的實(shí)現(xiàn)方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03
對(duì)于input 框限定輸入值為浮點(diǎn)型的js代碼
下面小編就為大家?guī)?lái)一篇對(duì)于input 框限定輸入值為浮點(diǎn)型的js代碼。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09
JavaScript實(shí)現(xiàn)圖片懶加載與預(yù)加載的代碼詳解
圖片懶加載與預(yù)加載是前端優(yōu)化中比較常見的方法,也是前端面試中會(huì)被問(wèn)到的問(wèn)題,如果不做懶加載和預(yù)加載,瀏覽器的回流重繪很快,而圖片的加載是需要發(fā)送網(wǎng)絡(luò)請(qǐng)求的,一次性發(fā)很多請(qǐng)求就會(huì)導(dǎo)致網(wǎng)絡(luò)的堵塞,影響用戶體驗(yàn),接下來(lái)就讓我們來(lái)實(shí)現(xiàn)一下懶加載以及預(yù)加載的效果2025-03-03
分享一個(gè)自己寫的table表格排序js插件(高效簡(jiǎn)潔)
在前不久做的一個(gè)web項(xiàng)目中,需要實(shí)現(xiàn)js表格排序的效果,當(dāng)時(shí)為了省事,就在網(wǎng)上找了幾個(gè)相關(guān)的js插件2011-10-10
JS實(shí)現(xiàn)獲取毫秒值及轉(zhuǎn)換成年月日時(shí)分秒的方法
這篇文章主要介紹了JS實(shí)現(xiàn)獲取毫秒值及轉(zhuǎn)換成年月日時(shí)分秒的方法,結(jié)合實(shí)例形式分析了javascript常見的Date()日期時(shí)間獲取、轉(zhuǎn)換相關(guān)操作技巧,需要的朋友可以參考下2018-08-08

