目录
一、Token 详解
1. Token 的定义与作用
Token(令牌)是用于在客户端和服务器之间安全传递用户身份信息的一种凭证,通常用于身份验证和授权流程。
-
核心作用:
-
身份验证(Authentication):验证用户身份(如登录状态)。
-
授权(Authorization):授予用户访问特定资源的权限(如 API 端点)。
-
-
常见类型:
-
JWT(JSON Web Token):最流行的无状态令牌格式,包含头部、载荷和签名。
-
OAuth2 Token:用于第三方授权(如使用 Google 登录)。
-
Session Token:传统有状态会话标识(如 Session ID)。
-
2. Token 的工作流程
1. 用户登录 → 服务器验证凭据 → 生成 Token → 返回给客户端
2. 客户端存储 Token(如 localStorage、Cookie)
3. 客户端发起请求时携带 Token(通常通过 HTTP 头)
4. 服务器验证 Token → 授权访问资源
3. Token 的优势
-
无状态性:服务器无需存储会话信息(适合分布式系统)。
-
跨域支持:易于在多个服务间传递用户身份(如微服务架构)。
-
安全性:可通过签名(JWT)或加密防止篡改。
4. Token 的安全实践
-
存储方式:
-
推荐:使用
httpOnly
、Secure
、SameSite=Strict
的 Cookie(防 XSS)。 -
次选:
localStorage
或sessionStorage
(需防范 XSS)。
-
-
传输方式:
-
通过
Authorization
请求头传输(如Bearer <token>
)。
-
-
过期时间:
-
设置短期有效的 Token(如 15 分钟),配合 Refresh Token 续期。
-
5. JWT 结构示例
Header: {"alg": "HS256", "typ": "JWT"}
Payload: {"sub": "user123", "exp": 1620000000}
Signature: HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
二、Axios 拦截器详解
1. 拦截器的作用
拦截器允许在请求发送前或响应返回后,统一添加逻辑(如添加 Token、处理错误)。
2. 请求拦截器
axios.interceptors.request.use(
config => {
// 请求发送前的处理(如添加 Token)
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
error => {
// 请求错误处理
return Promise.reject(error);
}
);
3. 响应拦截器
axios.interceptors.response.use(
response => {
// 响应成功处理(状态码 2xx)
return response.data; // 直接返回数据,简化后续处理
},
async error => {
// 响应错误处理(状态码非 2xx 或网络错误)
const originalRequest = error.config;
// Token 过期且未重试过 → 尝试刷新 Token
if (error.response?.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
try {
const newToken = await refreshToken(); // 刷新 Token
localStorage.setItem('token', newToken);
originalRequest.headers.Authorization = `Bearer ${newToken}`;
return axios(originalRequest); // 重试原请求
} catch (refreshError) {
logout(); // 刷新失败 → 跳转登录页
return Promise.reject(refreshError);
}
}
// 其他错误统一处理
return Promise.reject(error);
}
);
4. 拦截器常见场景
-
自动添加 Token:统一为所有请求添加
Authorization
头。 -
Token 过期自动刷新:401 错误时刷新 Token 并重试请求。
-
统一错误处理:网络错误、服务器错误等全局捕获。
-
加载状态管理:显示/隐藏全局加载动画。
5. 移除拦截器
const requestInterceptor = axios.interceptors.request.use(...);
const responseInterceptor = axios.interceptors.response.use(...);
// 移除拦截器
axios.interceptors.request.eject(requestInterceptor);
axios.interceptors.response.eject(responseInterceptor);
三、完整代码示例
1. Token 管理 + Axios 拦截器
// 封装 Axios 实例
const api = axios.create({
baseURL: 'https://api.example.com',
});
// 请求拦截器:添加 Token
api.interceptors.request.use(
config => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
error => Promise.reject(error)
);
// 响应拦截器:处理 Token 过期
api.interceptors.response.use(
response => response.data,
async error => {
const originalRequest = error.config;
// Token 过期且未重试过
if (error.response?.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
try {
const newToken = await refreshToken();
localStorage.setItem('token', newToken);
originalRequest.headers.Authorization = `Bearer ${newToken}`;
return api(originalRequest);
} catch (refreshError) {
logout();
return Promise.reject(refreshError);
}
}
// 其他错误处理
return Promise.reject(error);
}
);
// 刷新 Token 的函数
async function refreshToken() {
const refreshToken = localStorage.getItem('refreshToken');
const response = await axios.post('/auth/refresh', { refreshToken });
return response.data.token;
}
// 退出登录
function logout() {
localStorage.removeItem('token');
localStorage.removeItem('refreshToken');
window.location.href = '/login';
}
四、总结
-
Token:身份验证与授权的核心凭证,需安全存储和传输。
-
Axios 拦截器:实现全局请求/响应逻辑(如 Token 管理、错误处理),提升代码复用性和可维护性。
-
最佳实践:
-
使用
httpOnly
Cookie 存储 Token(防 XSS)。 -
短期 Token + Refresh Token 提升安全性。
-
拦截器中处理 Token 刷新避免并发问题。
-
五、axios高级配置
1. 全局默认配置
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = 'Bearer token123';
axios.defaults.timeout = 5000; // 超时时间(毫秒)
2. 创建实例(隔离配置)
const api = axios.create({
baseURL: 'https://api.example.com',
timeout: 3000
});
api.get('/data'); // 使用实例发送请求
3. 取消请求
使用 CancelToken(旧版):
const source = axios.CancelToken.source();
axios.get('/data', {
cancelToken: source.token
}).catch(error => {
if (axios.isCancel(error)) {
console.log('请求被取消:', error.message);
}
});
// 取消请求
source.cancel('用户手动取消');
使用 AbortController(新版,推荐):
const controller = new AbortController();
axios.get('/data', {
signal: controller.signal
}).catch(error => {
if (error.name === 'CanceledError') {
console.log('请求已取消');
}
});
// 取消请求
controller.abort();
4. 并发请求
const request1 = axios.get('/data1');
const request2 = axios.get('/data2');
axios.all([request1, request2])
.then(axios.spread((res1, res2) => {
console.log(res1.data, res2.data);
}));
5. 文件上传
const formData = new FormData();
formData.append('file', fileInput.files[0]);
axios.post('/upload', formData, {
headers: { 'Content-Type': 'multipart/form-data' }
});
6. 文件下载
axios.get('/download', {
responseType: 'blob' // 指定响应类型为二进制流
}).then(response => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'file.pdf');
document.body.appendChild(link);
link.click();
});
六、XSS(跨站脚本攻击)
1. 攻击原理
-
定义:攻击者向网页注入恶意脚本(JavaScript、HTML、CSS),当其他用户访问该页面时,脚本在用户浏览器执行,窃取数据或劫持会话。
-
类型:
-
存储型 XSS:恶意脚本永久存储在目标服务器(如论坛评论)。
-
反射型 XSS:恶意脚本通过 URL 参数反射到页面(如钓鱼链接)。
-
DOM 型 XSS:前端 JavaScript 动态修改 DOM 时触发漏洞。
-
2. 攻击示例
// 用户输入未过滤,直接渲染到页面
用户评论内容:<script>stealCookie()</script>
3. 防御措施
-
输入过滤与转义:
-
对用户输入的内容进行 HTML 转义(如
<
→<
)。 -
使用安全的库(如
DOMPurify
)清理 HTML。
-
-
Content Security Policy(CSP):
Content-Security-Policy: default-src 'self'; script-src 'self' trusted.com
-
限制页面只能加载指定来源的脚本、样式等资源。
-
-
设置 HttpOnly Cookie:
-
防止 JavaScript 通过
document.cookie
读取敏感 Cookie。
// 服务器设置 Cookie Set-Cookie: sessionId=abc123; HttpOnly; Secure; SameSite=Strict
-
七、CSRF(跨站请求伪造)
1. 攻击原理
-
定义:攻击者诱导用户访问恶意页面,该页面自动向目标网站发起请求(利用用户已登录的 Cookie)。
-
示例:
<!-- 恶意页面中的图片标签 --> <img src="https://bank.com/transfer?to=attacker&amount=1000">
2. 防御措施
-
CSRF Token:
-
服务器生成随机 Token 嵌入表单或请求头,验证请求的合法性。
<form action="/transfer" method="POST"> <input type="hidden" name="csrf_token" value="随机值"> </form>
-
-
SameSite Cookie:
-
限制 Cookie 仅在相同站点请求中发送。
Set-Cookie: sessionId=abc123; SameSite=Strict; Secure
-
Strict:完全禁止第三方 Cookie。
-
Lax:允许安全导航(如链接跳转)携带 Cookie。
-
None:允许所有请求携带 Cookie(需配合
Secure
)。
-
-
验证请求来源:
-
检查
Origin
或Referer
头部是否来自合法域名。
-
八、Token 在防御中的应用
1. Token 类型
-
CSRF Token:防御 CSRF 攻击,确保请求来自合法页面。
-
JWT(JSON Web Token):用于无状态身份验证,包含签名防篡改。
2. 安全实践
-
存储方式:
-
CSRF Token:存储在服务器 Session 或加密 Cookie 中。
-
JWT:通过
httpOnly
+Secure
Cookie 存储,或前端存储但结合短期有效期。
-
-
传输方式:
-
CSRF Token:嵌入表单隐藏字段或请求头(如
X-CSRF-Token
)。 -
JWT:通过
Authorization: Bearer <token>
请求头传输。
-
3. JWT 安全增强
-
签名验证:使用强加密算法(如 HS256、RS256)。
-
有效期控制:设置短期有效的
exp
字段,配合 Refresh Token 续期。 -
黑名单机制:注销时使特定 Token 失效。
九、总结
-
XSS 防御核心:防止恶意脚本注入,隔离用户输入与代码执行。
-
CSRF 防御核心:确保请求来源合法,阻断伪造请求。
-
Token 安全:结合存储安全(HttpOnly)、传输安全(HTTPS)和有效期管理。
综合防御策略:
攻击类型 | 防御措施 |
---|---|
XSS | 输入过滤 + CSP + HttpOnly Cookie + 避免 innerHTML 直接渲染用户输入。 |
CSRF | CSRF Token + SameSite Cookie + 验证请求来源。 |
Token 安全 | 使用 HTTPS + 安全存储(HttpOnly Cookie) + 短期有效 + 签名验证。 |