// 登录成功后
const token = 'your_jwt_token_here';
localStorage.setItem('auth_token', token);
// 后续请求时带上
axios.interceptors.request.use((config) => {
const token = localStorage.getItem('auth_token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
let inMemoryToken = null;
// 登录成功后
const login = async () => {
const response = await loginAPI(username, password);
inMemoryToken = response.data.token; // 存到内存变量
};
// 请求拦截器中添加
axios.interceptors.request.use((config) => {
if (inMemoryToken) {
config.headers.Authorization = `Bearer ${inMemoryToken}`;
}
return config;
});
// 退出登录或页面刷新时,Token 消失
优点:
- 安全性极高:由于 Token 只存在于当前页面的内存中,关闭页面或刷新页面后 Token 立即消失。XSS 攻击者很难通过一次性注入的脚本持续地窃取到 Token(除非攻击代码常驻内存)。
缺点:
- 体验差:页面一旦刷新,Token 就没了,用户需要重新登录。这对于单页面应用 (SPA) 来说是致命的。
结论: 适用于安全要求极高、不介意频繁登录的场景(如银行系统)。 对于普通 Web 应用,体验不可接受。
终极方案:组合拳 + 架构思维
既然没有完美的银弹,现代前端的最佳实践通常是 组合方案 和 架构优化。
实践一:Cookie(HttpOnly + Secure) + 防御 CSRF
这是最传统但依然非常稳健的方案。
- 后端在登录成功后,设置一个
HttpOnly、Secure 的 Cookie 来存放 Token(可以是 JWT,也可以是 Session ID)。
- 前端基本不用操心 Token 的存储和携带问题,由浏览器自动完成。
- 后端必须部署完善的 CSRF 防护策略,例如:
- 从 Cookie 中读取 Token 或 Session ID 进行身份验证。
- 同时,要求请求必须携带一个额外的(由后端生成并通过 API 返回给前端的)
X-CSRF-Token Header,并与 Session 中存储的值进行比对。
实践二:Access Token + Refresh Token
这是目前 API 接口认证非常流行的方案,完美解决了内存存储体验差的问题。
- 登录:用户输入密码登录。
- 返回双 Token:服务端返回两个 Token:
access_token:短期有效(例如 2 小时),用于请求受保护的 API。
refresh_token:长期有效(例如 7 天),仅用于获取新的 access_token,不应具备API访问权限。
- 存储策略:
access_token:存入内存。这样即使被 XSS 窃取,有效期也很短,风险可控。
refresh_token:存入 HttpOnly Cookie。因为它有效期长,必须严加保护。由于其本身不直接用于业务请求,即使遭遇 CSRF,攻击者也无法用它来做任何关键操作(只能用来换一个短期的 access_token,而该 access_token 又会因为存在于内存而难以被攻击者获取)。
- 无感刷新:当
access_token 过期后,前端自动(通过 refresh_token)调用刷新接口获取新的 access_token,用户无感知。
这个方案在安全性和用户体验之间取得了绝佳的平衡,是当前众多大型应用的首选。
总结与建议
给你的最终建议:
- 如果你在做的是一个简单的、内部使用的、对安全性要求不高的工具,用
localStorage 图个方便也无可厚非,但要清楚风险。
- 如果你在做的是一个传统的、服务端渲染的多页应用,使用
HttpOnly Cookie 并配套 CSRF 防护是标准做法。
- 如果你在做的是一个现代化的 SPA(如 React/Vue 应用),强烈推荐研究并采用 Access Token (内存) + Refresh Token (
HttpOnly Cookie) 的方案。
安全没有绝对,只有相对的权衡。理解每种方案的利弊,并根据你的实际业务场景做出最适合的选择,才是最重要的。
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。