跳到主要内容

敏感数据安全处理

场景

前端页面需要展示和处理用户手机号、身份证号、银行卡号等敏感信息,如何确保安全?

方案设计

1. 数据脱敏展示

data-mask.ts
const maskRules = {
// 手机号:138****5678
phone: (val: string) => val.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2'),

// 身份证:110***********1234
idCard: (val: string) => val.replace(/(\d{3})\d{11}(\d{4})/, '$1***********$2'),

// 银行卡:**** **** **** 5678
bankCard: (val: string) => `**** **** **** ${val.slice(-4)}`,

// 姓名:张*三
name: (val: string) => {
if (val.length <= 2) return val[0] + '*';
return val[0] + '*'.repeat(val.length - 2) + val[val.length - 1];
},

// 邮箱:z***n@example.com
email: (val: string) => {
const [user, domain] = val.split('@');
return `${user[0]}***${user[user.length - 1]}@${domain}`;
},
};

function mask(type: keyof typeof maskRules, value: string): string {
if (!value) return '';
return maskRules[type](value);
}

2. 前端存储安全

secure-storage.ts
// ❌ 永远不要做
localStorage.setItem('token', accessToken); // Token 直接存 localStorage
localStorage.setItem('password', password); // 密码存前端

// ✅ Token 存储最佳实践
// 方案 1:HttpOnly Cookie(推荐,JS 无法读取)
// Set-Cookie: access_token=xxx; HttpOnly; Secure; SameSite=Strict

// 方案 2:如果必须存前端,用内存存储
class TokenStore {
private token: string | null = null;

setToken(token: string) { this.token = token; }
getToken() { return this.token; }
clearToken() { this.token = null; }
}
// 页面刷新后需要用 refresh_token 重新获取

3. 传输安全

encryption.ts
// 敏感数据传输加密(如密码)
// 前端用 RSA 公钥加密,后端用私钥解密

async function encryptPassword(password: string, publicKey: string): Promise<string> {
const key = await crypto.subtle.importKey(
'spki',
base64ToArrayBuffer(publicKey),
{ name: 'RSA-OAEP', hash: 'SHA-256' },
false,
['encrypt']
);

const encrypted = await crypto.subtle.encrypt(
{ name: 'RSA-OAEP' },
key,
new TextEncoder().encode(password)
);

return arrayBufferToBase64(encrypted);
}

function base64ToArrayBuffer(base64: string): ArrayBuffer {
const binary = atob(base64);
const bytes = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i);
}
return bytes.buffer;
}

function arrayBufferToBase64(buffer: ArrayBuffer): string {
return btoa(String.fromCharCode(...new Uint8Array(buffer)));
}

4. 安全检查清单

场景风险措施
展示敏感信息数据泄露脱敏显示、点击查看完整
存储 TokenXSS 窃取HttpOnly Cookie / 内存存储
密码传输中间人截获HTTPS + RSA 加密
接口返回过度暴露后端按需返回、最小权限
Console 输出信息泄露生产环境移除 console.log
错误日志含敏感信息上报前过滤脱敏

常见面试问题

Q1: 前端能做加密吗?有意义吗?

答案

前端加密有一定意义但不绝对可靠

  • 有意义:防止中间人明文截获(HTTPS 已覆盖)、防止后端日志记录明文密码、防止浏览器扩展嗅探
  • 局限性:前端代码可被查看、密钥管理困难、无法防止中间人替换公钥

核心原则:安全不能只靠前端,HTTPS 是底线,前端加密是额外防护层。

Q2: Token 存在哪里最安全?

答案

方案安全性XSS 风险CSRF 风险
HttpOnly Cookie★★★免疫需防护
内存变量★★★较安全免疫
localStorage易被窃取免疫
sessionStorage★★易被窃取免疫

推荐:Access Token 放 HttpOnly Cookie,Refresh Token 也放 HttpOnly Cookie(设 Path=/api/refresh)。

相关链接