前端安全
XSS 防护
输入过滤
javascript
// 过滤 HTML 标签
function escapeHtml(str) {
return str.replace(/[&<>"']/g, function(match) {
const escape = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
return escape[match];
});
}
// 使用
const userInput = '<script>alert("xss")</script>';
const safeInput = escapeHtml(userInput);CSP 配置
html
<!-- Content Security Policy -->
<meta http-equiv="Content-Security-Policy" content="
default-src 'self';
script-src 'self' 'unsafe-inline' 'unsafe-eval';
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
connect-src 'self' https://api.example.com;
">CSRF 防护
Token 验证
javascript
// 后端生成 Token
const csrfToken = generateToken();
// 前端发送请求时带上 Token
fetch('/api/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': csrfToken
},
body: JSON.stringify(data)
});SameSite Cookie
javascript
// 设置 Cookie
document.cookie = "session=value; SameSite=Strict; Secure";点击劫持防护
X-Frame-Options
javascript
// 设置响应头
res.setHeader('X-Frame-Options', 'DENY');Frame Busting
javascript
// 防止页面被嵌套
if (window.top !== window.self) {
window.top.location = window.self.location;
}数据安全
敏感信息处理
javascript
// 加密敏感数据
const encryptedData = CryptoJS.AES.encrypt(
JSON.stringify(data),
secretKey
).toString();
// 解密数据
const decryptedData = JSON.parse(
CryptoJS.AES.decrypt(encryptedData, secretKey)
.toString(CryptoJS.enc.Utf8)
);本地存储安全
javascript
// 使用加密的本地存储
const secureStorage = {
set(key, value) {
const encrypted = CryptoJS.AES.encrypt(
JSON.stringify(value),
secretKey
).toString();
localStorage.setItem(key, encrypted);
},
get(key) {
const encrypted = localStorage.getItem(key);
if (!encrypted) return null;
return JSON.parse(
CryptoJS.AES.decrypt(encrypted, secretKey)
.toString(CryptoJS.enc.Utf8)
);
}
};密码安全
密码强度验证
javascript
function validatePassword(password) {
const minLength = 8;
const hasUpperCase = /[A-Z]/.test(password);
const hasLowerCase = /[a-z]/.test(password);
const hasNumbers = /\d/.test(password);
const hasSpecialChar = /[!@#$%^&*]/.test(password);
return (
password.length >= minLength &&
hasUpperCase &&
hasLowerCase &&
hasNumbers &&
hasSpecialChar
);
}密码加密
javascript
// 使用 bcrypt 加密密码
const saltRounds = 10;
const hashedPassword = await bcrypt.hash(password, saltRounds);
// 验证密码
const isMatch = await bcrypt.compare(password, hashedPassword);安全配置
HTTPS 配置
nginx
# nginx.conf
server {
listen 443 ssl;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
}安全响应头
javascript
// 设置安全相关的响应头
app.use((req, res, next) => {
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-XSS-Protection', '1; mode=block');
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
next();
});最佳实践
1. 输入验证
- 客户端验证
- 服务器端验证
- 数据格式化
- 错误处理
2. 输出编码
- HTML 编码
- URL 编码
- JavaScript 编码
- CSS 编码
3. 会话管理
- 安全的 Cookie 设置
- 会话超时
- 登录限制
- 注销处理
4. 错误处理
- 友好的错误提示
- 日志记录
- 错误监控
- 异常恢复
学习资源
官方文档
视频课程
- 慕课网
- 极客时间
- B站技术区
- YouTube 技术频道