您现在的位置是:网站首页 > 敏感信息在前端的存储问题文章详情
敏感信息在前端的存储问题
陈川
【
前端安全
】
15643人已围观
4700字
敏感信息在前端的存储问题
前端开发中处理敏感信息时,存储方式的选择直接影响系统安全性。错误的存储方案可能导致数据泄露、会话劫持甚至法律合规风险。
常见敏感数据类型
需要特别关注的敏感数据类型包括但不限于:
-
用户身份凭证
- 登录令牌(JWT、Session ID)
- API密钥
- OAuth令牌
-
个人隐私数据
- 身份证号码
- 银行卡信息
- 医疗记录
-
业务敏感数据
- 未公开的交易金额
- 内部系统配置
- 权限标识符
高风险存储方式及问题
localStorage的永久存储风险
// 危险示例:将JWT存储在localStorage
localStorage.setItem('auth_token', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...');
问题表现:
- XSS攻击可完全读取所有存储内容
- 无自动过期机制
- 同源策略下所有页面共享
cookie的错误配置
// 不安全cookie设置
document.cookie = `session_id=3f8d7b2a1c; path=/`;
典型漏洞模式:
- 缺少HttpOnly标志导致JS可读
- 未设置Secure标志时通过HTTP传输
- Domain过于宽松导致子域名共享
URL参数暴露
// 敏感数据通过URL传递
window.location.href = `/reset-password?token=${resetToken}`;
安全隐患:
- 浏览器历史记录永久保存
- 第三方扩展可能读取URL
- 服务器日志完整记录
安全存储实践方案
会话管理最佳实践
// 安全cookie设置示例(需后端配合)
fetch('/login', {
method: 'POST',
credentials: 'include' // 确保cookie能被正确设置
});
// 后端应返回:Set-Cookie: sessionId=xxx; HttpOnly; Secure; SameSite=Strict
关键配置组合:
- HttpOnly + Secure + SameSite
- 短期过期时间(如30分钟)
- 服务端签名验证
临时敏感数据处理
// 使用内存存储临时令牌
let temporaryToken = null;
function fetchToken() {
return api.getToken().then(token => {
temporaryToken = token; // 仅保存在内存中
setTimeout(() => { temporaryToken = null }, 300000); // 5分钟后自动清除
});
}
内存存储特点:
- 页面刷新即丢失
- 不受XSS持久化影响
- 需配合自动清理机制
Web Crypto API的应用
// 使用SubtleCrypto进行客户端加密
async function encryptData(data, password) {
const encoder = new TextEncoder();
const keyMaterial = await crypto.subtle.importKey(
'raw',
encoder.encode(password),
{ name: 'PBKDF2' },
false,
['deriveKey']
);
const salt = crypto.getRandomValues(new Uint8Array(16));
const key = await crypto.subtle.deriveKey(
{ name: 'PBKDF2', salt, iterations: 100000, hash: 'SHA-256' },
keyMaterial,
{ name: 'AES-GCM', length: 256 },
false,
['encrypt', 'decrypt']
);
const iv = crypto.getRandomValues(new Uint8Array(12));
const encrypted = await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv },
key,
encoder.encode(data)
);
return { encrypted, iv, salt };
}
加密要点:
- 使用强随机数生成IV和salt
- 高迭代次数的密钥派生
- 避免存储解密密钥
框架特定解决方案
React Context的安全用法
// 创建安全上下文
const AuthContext = React.createContext(null);
function AuthProvider({ children }) {
const [token, setToken] = useState(null);
// 自动清理机制
useEffect(() => {
const timer = setTimeout(() => setToken(null), 3600000);
return () => clearTimeout(timer);
}, [token]);
return (
<AuthContext.Provider value={{ token, setToken }}>
{children}
</AuthContext.Provider>
);
}
// 使用示例
function Dashboard() {
const { token } = useContext(AuthContext);
// token仅存在于内存中
}
Vue响应式数据的保护
// 使用非响应式存储敏感数据
const secretStore = {
_data: null,
get secret() {
return this._data;
},
set secret(value) {
this._data = value;
if (value) setTimeout(() => this._data = null, 1800000);
}
}
// 在组件中使用
export default {
methods: {
storeToken(token) {
secretStore.secret = token; // 不会触发Vue响应式系统
}
}
}
合规性要求考量
GDPR相关规范
- 数据最小化原则:仅存储必要信息
- 用户明确同意:对cookie存储的特殊要求
- 数据主体权利:提供清除接口
PCI DSS支付标准
- 禁止前端存储完整信用卡号
- 允许显示的最后四位需脱敏处理
- 必须使用符合标准的加密算法
监控与应急措施
异常访问检测
// 监听storage事件检测异常访问
window.addEventListener('storage', (event) => {
if (event.key === 'auth_token' && event.oldValue !== event.newValue) {
analytics.log('Suspicious token modification', {
oldValue: event.oldValue?.slice(0, 5) + '...',
newValue: event.newValue?.slice(0, 5) + '...'
});
}
});
数据泄露响应
- 立即使受影响令牌失效
- 强制用户重新认证
- 审计日志分析访问模式
- 根据法规要求进行通知
开发环境特殊处理
敏感配置隔离
// config.dev.js
export default {
apiKey: 'dev_public_key'
};
// config.prod.js
export default {
apiKey: process.env.API_KEY // 通过构建工具注入
};
// 实际使用
import config from './config.' + process.env.NODE_ENV;
注意事项:
- 禁止将真实密钥提交到版本控制
- 使用环境变量和.gitignore配合
- 预提交钩子检查敏感信息
浏览器API的局限与补充
IndexedDB的安全增强
// 加密后存储到IndexedDB
async function secureStore(dbName, key, value, password) {
const encrypted = await encryptData(value, password);
const db = await indexedDB.open(dbName, 1);
db.onupgradeneeded = (event) => {
event.target.result.createObjectStore('secureStore');
};
return new Promise((resolve) => {
db.onsuccess = (event) => {
const tx = event.target.result.transaction('secureStore', 'readwrite');
tx.objectStore('secureStore').put(encrypted, key);
resolve();
};
});
}
补充方案:
- 使用Web Workers处理加解密
- 存储主密钥使用硬件安全模块(HSM)
- 定期轮换加密密钥