您现在的位置是:网站首页 > 防止数据泄露的最佳实践文章详情
防止数据泄露的最佳实践
陈川
【
前端安全
】
52901人已围观
6447字
数据加密与传输安全
前端处理敏感数据时,必须确保传输和存储过程中的加密。HTTPS是基础要求,但仅此不够。对于特别敏感的数据,建议在前端进行二次加密。
// 使用Web Crypto API进行客户端加密示例
async function encryptData(data, secretKey) {
const encoder = new TextEncoder();
const dataBuffer = encoder.encode(data);
const key = await crypto.subtle.importKey(
'raw',
encoder.encode(secretKey),
{ name: 'AES-GCM' },
false,
['encrypt']
);
const iv = crypto.getRandomValues(new Uint8Array(12));
const encrypted = await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv },
key,
dataBuffer
);
return {
iv: Array.from(iv).join(','),
content: Array.from(new Uint8Array(encrypted)).join(',')
};
}
表单提交时,避免直接发送明文密码。可以采用SRP协议或类似机制,确保密码在传输前已经过不可逆处理。
输入验证与净化
所有用户输入都应视为不可信的。前端验证不能替代后端验证,但能减少无效请求和基础攻击。
// 严格的输入验证示例
function sanitizeInput(input) {
// 移除HTML标签
let sanitized = input.replace(/<[^>]*>?/gm, '');
// 防止XSS
sanitized = sanitized.replace(/[&<>"'`=\/]/g, function(match) {
return {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
'/': '/',
'`': '`',
'=': '='
}[match];
});
// 限制长度
return sanitized.substring(0, 255);
}
对于富文本输入,使用经过严格配置的库如DOMPurify:
import DOMPurify from 'dompurify';
const clean = DOMPurify.sanitize(dirty, {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a'],
ALLOWED_ATTR: ['href', 'title'],
FORBID_ATTR: ['style', 'onerror']
});
安全的存储实践
客户端存储敏感数据需格外谨慎。避免在localStorage或sessionStorage中存储令牌、密码等。
// 更安全的存储方案
const secureStorage = {
setItem: async (key, value) => {
const encrypted = await encryptData(value, 'your-secret-key');
localStorage.setItem(key, JSON.stringify(encrypted));
},
getItem: async (key) => {
const encrypted = JSON.parse(localStorage.getItem(key));
if (!encrypted) return null;
return await decryptData(encrypted, 'your-secret-key');
}
};
// 使用示例
await secureStorage.setItem('auth_token', 'sensitive-token-value');
const token = await secureStorage.getItem('auth_token');
对于必须存储的令牌,设置合理过期时间,并实现自动失效机制。
内容安全策略(CSP)实施
CSP能有效减少XSS攻击风险。以下是一个严格的CSP配置示例:
<meta http-equiv="Content-Security-Policy" content="
default-src 'none';
script-src 'self' 'unsafe-inline' 'unsafe-eval' https://trusted.cdn.com;
style-src 'self' 'unsafe-inline';
img-src 'self' data: https://trusted.images.com;
font-src 'self';
connect-src 'self' https://api.yourapp.com;
frame-src 'none';
object-src 'none';
base-uri 'self';
form-action 'self';
">
定期审查CSP策略,使用report-uri收集违规报告:
Content-Security-Policy: default-src 'self'; report-uri https://yourapp.com/csp-report
第三方依赖管理
前端项目常依赖大量第三方库,这些都可能成为攻击向量。
- 定期审计依赖:
npm audit
npx snyk test
- 锁定版本号:
{
"dependencies": {
"react": "16.13.1", // 精确版本
"lodash": "^4.17.15" // 仅允许补丁更新
}
}
- 使用子资源完整性(SRI):
<script
src="https://cdn.example.com/library.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
crossorigin="anonymous">
</script>
敏感信息处理
开发过程中容易意外暴露敏感信息:
// 错误示例 - 硬编码凭证
const API_KEY = 'sk_live_1234567890';
// 正确做法 - 使用环境变量
const API_KEY = process.env.REACT_APP_API_KEY;
// 构建时确保不会打包进客户端代码
if (typeof API_KEY === 'undefined') {
throw new Error('Missing required environment variable');
}
前端代码中避免处理敏感业务逻辑,如:
- 密码加密盐值生成
- 支付金额验证
- 权限检查核心逻辑
错误处理与日志记录
不当的错误处理可能泄露系统信息:
// 错误示例 - 暴露堆栈信息
try {
riskyOperation();
} catch (err) {
alert(`Error: ${err.stack}`);
}
// 正确做法 - 通用错误消息
try {
riskyOperation();
} catch {
alert('操作失败,请重试或联系支持');
console.error('Operation failed', error); // 开发环境
}
客户端日志收集需过滤敏感字段:
function safeLog(data) {
const sensitiveFields = ['password', 'creditCard', 'token'];
const sanitized = {...data};
sensitiveFields.forEach(field => {
if (sanitized[field]) {
sanitized[field] = '***REDACTED***';
}
});
sendToLoggingService(sanitized);
}
跨域资源共享(CORS)配置
错误的CORS配置会导致数据泄露:
// Express示例 - 过于宽松的配置
app.use(cors()); // 危险!允许所有来源
// 安全的CORS配置
const corsOptions = {
origin: [
'https://yourapp.com',
'https://admin.yourapp.com'
],
methods: ['GET', 'POST', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization'],
maxAge: 86400,
credentials: true
};
app.use(cors(corsOptions));
对于敏感操作,增加预检请求验证:
app.options('/api/transfer', cors(corsOptions)); // 单独处理OPTIONS
app.post('/api/transfer', cors(corsOptions), handleTransfer);
前端监控与异常检测
实现实时监控可及时发现潜在泄露:
// 使用Sentry监控前端错误
import * as Sentry from '@sentry/browser';
Sentry.init({
dsn: 'your-dsn',
beforeSend(event) {
// 过滤敏感信息
if (event.request && event.request.data) {
event.request.data = sanitizeData(event.request.data);
}
return event;
}
});
// 手动捕获可疑行为
function detectSuspiciousActivity() {
if (window.performance.memory.usedJSHeapSize > threshold) {
Sentry.captureMessage('High memory usage detected');
}
}
安全头设置
除CSP外,其他安全头同样重要:
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Referrer-Policy: no-referrer-when-downgrade
Feature-Policy: geolocation 'none'; microphone 'none'
现代浏览器支持的权限策略:
Permissions-Policy: geolocation=(), camera=(), microphone=()
自动化安全测试
将安全检查集成到开发流程:
- 使用ESLint安全规则:
{
"extends": ["plugin:security/recommended"],
"rules": {
"security/detect-object-injection": "error",
"security/detect-possible-timing-attacks": "error"
}
}
- 添加预提交钩子:
#!/bin/sh
npm run lint-security && npm run audit
- CI/CD管道集成:
# .gitlab-ci.yml示例
security_scan:
stage: test
script:
- npm run audit
- npx snyk test
- npm run lint-security
allow_failure: false
浏览器安全特性利用
充分利用现代浏览器安全功能:
- 安全上下文限制:
// 检测是否在安全上下文中运行
if (window.isSecureContext) {
// 可以使用Web Crypto API等敏感功能
} else {
alert('请在HTTPS环境下使用此功能');
}
- 使用Credential Management API安全存储凭据:
navigator.credentials.store(
new PasswordCredential({
id: 'user123',
password: 's3cr3t',
name: 'User Name'
})
).then(() => {
console.log('Credential stored securely');
});
- 启用Cross-Origin隔离:
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin
上一篇: 前端加密存储方案
下一篇: 浏览器缓存的安全问题