持久登录的存储
实现持久登录的存储技术
⭐ 能实现持久登录的存储技术
1️⃣ Cookie
// 设置登录Cookie (7天过期)
document.cookie = "authToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...; max-age=604800; path=/; secure; SameSite=Strict";
document.cookie = "userId=123456; max-age=604800; path=/; secure; SameSite=Strict";
核心优势:
- ✅ 自动随每次HTTP请求发送到服务器
- ✅ 可设置过期时间(expires/max-age)
- ✅ 传统和最广泛支持的方式
- ✅ 服务器可直接读取验证身份
注意事项:
- ⚠️ 容量有限(~4KB)
- ⚠️ 安全敏感信息应设置HttpOnly防止XSS攻击
- ⚠️ 应设置Secure确保只通过HTTPS传输
2️⃣ localStorage
// 存储登录信息
localStorage.setItem('authToken', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...');
localStorage.setItem('userData', JSON.stringify({id: 123456,name: '张三',role: 'user',lastLogin: new Date().toISOString()
}));// 检查登录状态
function checkAuth() {const token = localStorage.getItem('authToken');if (token) {// 用户已登录,附加token到API请求return true;}return false;
}
核心优势:
- ✅ 永久保存直到手动清除
- ✅ 较大存储容量(~5MB)
- ✅ 可存储更复杂的用户信息
- ✅ 适合现代前端应用(SPA架构)
注意事项:
- ⚠️ 不会自动发送到服务器,需手动附加到请求
- ⚠️ 易受XSS攻击,不应存储敏感原始凭证
- ⚠️ 同源限制(只能被同域使用)
3️⃣ IndexedDB
// 初始化用户认证数据库
function initAuthDB() {return new Promise((resolve, reject) => {const request = indexedDB.open('AuthDB', 1);request.onupgradeneeded = e => {const db = e.target.result;if (!db.objectStoreNames.contains('authData')) {db.createObjectStore('authData', { keyPath: 'id' });}};request.onsuccess = e => resolve(e.target.result);request.onerror = e => reject(e.target.error);});
}// 保存认证信息
async function saveAuthData(userData) {const db = await initAuthDB();return new Promise((resolve, reject) => {const tx = db.transaction('authData', 'readwrite');const store = tx.objectStore('authData');// 存储复杂的认证信息store.put({id: 'currentUser',token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',user: userData,permissions: ['read', 'write', 'admin'],refreshToken: 'refresh_token_here',expiresAt: new Date().getTime() + (7 * 24 * 60 * 60 * 1000) // 7天后过期});tx.oncomplete = () => resolve(true);tx.onerror = e => reject(e.target.error);});
}
核心优势:
- ✅ 永久保存,容量大(几百MB)
- ✅ 支持复杂数据结构
- ✅ 可存储完整用户配置文件和权限数据
- ✅ 支持事务和索引,更高级的数据操作
注意事项:
- ⚠️ API较复杂,学习曲线陡峭
- ⚠️ 同样需要手动添加到请求中
- ⚠️ 主要用于复杂或大型离线应用
🔄 实际应用方案比较
Cookie + 服务器会话 (传统方案)
JWT + localStorage (现代SPA方案)
💡 最佳实践对比
方案 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
Cookie + Session | 成熟稳定,自动发送 | 服务器需保存会话状态 | 传统网站,需要严格安全控制 |
JWT + localStorage | 无服务器状态,支持分布式 | 手动管理,需防XSS攻击 | 现代SPA应用,前后端分离架构 |
刷新Token + IndexedDB | 可存储复杂授权信息 | 实现复杂 | 大型应用,需要完整权限管理 |
🔐 安全实践与优化技巧
1. 兼具安全与便利的方案
// 登录成功后
function handleLoginSuccess(response) {// 短期验证用Cookie (HttpOnly保护)// 由服务器设置,前端不可见// 长期刷新令牌用localStoragelocalStorage.setItem('refreshToken', response.refreshToken);localStorage.setItem('tokenExpiry', response.expiryTime);// 记住用户的基本信息localStorage.setItem('userInfo', JSON.stringify({id: response.userId,name: response.userName,avatar: response.avatar}));
}// 应用启动时检查
function checkAuthentication() {// 首先检查Cookie中的会话是否有效// (由服务器验证)// 如果会话无效但有刷新令牌const refreshToken = localStorage.getItem('refreshToken');const expiry = localStorage.getItem('tokenExpiry');if (refreshToken && new Date().getTime() < parseInt(expiry)) {// 使用刷新令牌获取新的访问令牌return api.refreshAuthentication(refreshToken).then(response => {// 更新身份验证状态handleLoginSuccess(response);return true;}).catch(() => {// 刷新失败,需要重新登录clearAuthData();return false;});}return Promise.resolve(false);
}
2. 安全存储登录凭证的最佳实践
📚 总结
-
⚠️ Cookie: 传统且可靠的持久登录方式,自动发送到服务器,适合同站点应用,但容量有限
-
🔑 localStorage: 现代前端应用首选,容量大,永久保存,但需手动添加到请求头,需防范XSS风险
-
💪 IndexedDB: 适用于需存储复杂用户数据和权限的大型应用,但API较复杂
-
🚀 综合方案:
- 访问令牌(JWT)用HttpOnly Cookie保存(安全)
- 刷新令牌用localStorage(便于长期保持登录)
- 基本用户信息用localStorage(快速访问,改善用户体验)
选择适合你的应用架构和安全需求的技术,实现最佳的持久登录体验!