237 lines
6.6 KiB
Markdown
237 lines
6.6 KiB
Markdown
# 安全响应头配置指南
|
||
|
||
本文档说明如何在生产环境中配置安全响应头,防止点击劫持等安全攻击。
|
||
|
||
## 已实施的安全措施
|
||
|
||
### 1. 开发环境(Vite)
|
||
已在 `vite.config.js` 中配置以下响应头:
|
||
- `X-Frame-Options: SAMEORIGIN` - 只允许同源页面嵌入
|
||
- `X-Content-Type-Options: nosniff` - 防止 MIME 类型嗅探
|
||
- `X-XSS-Protection: 1; mode=block` - 启用 XSS 过滤
|
||
- `Content-Security-Policy: frame-ancestors 'self'` - CSP 防止点击劫持
|
||
|
||
### 2. HTML Meta 标签
|
||
在 `index.html` 中添加了 CSP meta 标签作为备用防护。
|
||
|
||
## 生产环境配置
|
||
|
||
### Nginx 配置
|
||
|
||
在 Nginx 配置文件中添加以下响应头:
|
||
|
||
```nginx
|
||
server {
|
||
listen 80;
|
||
server_name your-domain.com;
|
||
|
||
# 安全响应头配置
|
||
# 防止点击劫持攻击
|
||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||
# 如果要完全禁止被嵌入,使用:
|
||
# add_header X-Frame-Options "DENY" always;
|
||
|
||
# 防止 MIME 类型嗅探
|
||
add_header X-Content-Type-Options "nosniff" always;
|
||
|
||
# XSS 保护
|
||
add_header X-XSS-Protection "1; mode=block" always;
|
||
|
||
# 内容安全策略(CSP)- 现代替代方案
|
||
add_header Content-Security-Policy "frame-ancestors 'self'" always;
|
||
|
||
# 强制 HTTPS(可选但推荐)
|
||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||
|
||
# 引用策略
|
||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||
|
||
location / {
|
||
root /path/to/your/dist;
|
||
try_files $uri $uri/ /index.html;
|
||
}
|
||
}
|
||
```
|
||
|
||
### Apache 配置
|
||
|
||
在 `.htaccess` 或 Apache 配置文件中添加:
|
||
|
||
```apache
|
||
<IfModule mod_headers.c>
|
||
# 防止点击劫持攻击
|
||
Header always set X-Frame-Options "SAMEORIGIN"
|
||
# 如果要完全禁止被嵌入,使用:
|
||
# Header always set X-Frame-Options "DENY"
|
||
|
||
# 防止 MIME 类型嗅探
|
||
Header always set X-Content-Type-Options "nosniff"
|
||
|
||
# XSS 保护
|
||
Header always set X-XSS-Protection "1; mode=block"
|
||
|
||
# 内容安全策略
|
||
Header always set Content-Security-Policy "frame-ancestors 'self'"
|
||
|
||
# 强制 HTTPS(可选但推荐)
|
||
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
|
||
|
||
# 引用策略
|
||
Header always set Referrer-Policy "strict-origin-when-cross-origin"
|
||
</IfModule>
|
||
```
|
||
|
||
### Node.js/Express 配置
|
||
|
||
如果使用 Express 作为服务器:
|
||
|
||
```javascript
|
||
const express = require('express');
|
||
const helmet = require('helmet'); // 推荐使用 helmet 中间件
|
||
|
||
const app = express();
|
||
|
||
// 使用 helmet 中间件(推荐)
|
||
app.use(helmet({
|
||
frameguard: {
|
||
action: 'sameorigin' // 或 'deny'
|
||
},
|
||
contentSecurityPolicy: {
|
||
directives: {
|
||
frameAncestors: ["'self'"]
|
||
}
|
||
}
|
||
}));
|
||
|
||
// 或手动设置响应头
|
||
app.use((req, res, next) => {
|
||
res.setHeader('X-Frame-Options', 'SAMEORIGIN');
|
||
res.setHeader('X-Content-Type-Options', 'nosniff');
|
||
res.setHeader('X-XSS-Protection', '1; mode=block');
|
||
res.setHeader('Content-Security-Policy', "frame-ancestors 'self'");
|
||
next();
|
||
});
|
||
|
||
app.use(express.static('dist'));
|
||
```
|
||
|
||
### 腾讯云静态网站托管配置
|
||
|
||
如果使用腾讯云静态网站托管,可以在 `cloudbaserc.json` 中添加:
|
||
|
||
```json
|
||
{
|
||
"envId": "your-env-id",
|
||
"framework": {
|
||
"name": "vue",
|
||
"plugins": {
|
||
"client": {
|
||
"path": "./package/dist",
|
||
"headers": [
|
||
{
|
||
"key": "X-Frame-Options",
|
||
"value": "SAMEORIGIN"
|
||
},
|
||
{
|
||
"key": "X-Content-Type-Options",
|
||
"value": "nosniff"
|
||
},
|
||
{
|
||
"key": "X-XSS-Protection",
|
||
"value": "1; mode=block"
|
||
},
|
||
{
|
||
"key": "Content-Security-Policy",
|
||
"value": "frame-ancestors 'self'"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
## X-Frame-Options 选项说明
|
||
|
||
### SAMEORIGIN
|
||
- **含义**:只允许同源(相同域名)的页面嵌入当前页面
|
||
- **使用场景**:当你需要在自己网站的其他页面中嵌入当前页面时
|
||
- **安全性**:中等,可防止外部网站的点击劫持攻击
|
||
|
||
### DENY
|
||
- **含义**:完全禁止任何页面嵌入当前页面
|
||
- **使用场景**:当你确定页面不需要被任何 iframe 嵌入时
|
||
- **安全性**:最高,提供最强的点击劫持防护
|
||
|
||
### ALLOW-FROM uri(已废弃)
|
||
- **含义**:允许特定 URI 的页面嵌入
|
||
- **状态**:已被主流浏览器废弃,不推荐使用
|
||
- **替代方案**:使用 CSP 的 `frame-ancestors` 指令
|
||
|
||
## CSP frame-ancestors 指令
|
||
|
||
CSP 的 `frame-ancestors` 是 `X-Frame-Options` 的现代替代方案,提供更灵活的控制:
|
||
|
||
```
|
||
Content-Security-Policy: frame-ancestors 'none' # 等同于 X-Frame-Options: DENY
|
||
Content-Security-Policy: frame-ancestors 'self' # 等同于 X-Frame-Options: SAMEORIGIN
|
||
Content-Security-Policy: frame-ancestors 'self' https://trusted.com # 允许特定域名
|
||
```
|
||
|
||
## 验证配置
|
||
|
||
### 方法1:浏览器开发者工具
|
||
1. 打开网站
|
||
2. 按 F12 打开开发者工具
|
||
3. 切换到 Network(网络)标签
|
||
4. 刷新页面
|
||
5. 点击主文档请求
|
||
6. 查看 Response Headers(响应头)
|
||
7. 确认 `X-Frame-Options` 和 `Content-Security-Policy` 存在
|
||
|
||
### 方法2:命令行测试
|
||
```bash
|
||
curl -I https://your-domain.com
|
||
```
|
||
|
||
### 方法3:在线工具
|
||
- [SecurityHeaders.com](https://securityheaders.com/)
|
||
- [Mozilla Observatory](https://observatory.mozilla.org/)
|
||
|
||
## 测试点击劫持防护
|
||
|
||
创建一个测试 HTML 文件:
|
||
|
||
```html
|
||
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<title>点击劫持测试</title>
|
||
</head>
|
||
<body>
|
||
<h1>尝试嵌入目标网站</h1>
|
||
<iframe src="https://your-domain.com" width="800" height="600"></iframe>
|
||
</body>
|
||
</html>
|
||
```
|
||
|
||
如果配置正确,iframe 将无法加载目标页面,浏览器控制台会显示类似错误:
|
||
```
|
||
Refused to display 'https://your-domain.com' in a frame because it set 'X-Frame-Options' to 'sameorigin'.
|
||
```
|
||
|
||
## 注意事项
|
||
|
||
1. **选择合适的策略**:根据业务需求选择 `SAMEORIGIN` 或 `DENY`
|
||
2. **同时使用多层防护**:建议同时配置 `X-Frame-Options` 和 CSP `frame-ancestors`
|
||
3. **HTTPS**:始终使用 HTTPS 以确保安全头不会被中间人攻击篡改
|
||
4. **测试兼容性**:部署后测试所有功能是否正常工作
|
||
5. **定期审计**:定期检查安全配置是否有效
|
||
|
||
## 相关资源
|
||
|
||
- [OWASP Clickjacking Defense Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html)
|
||
- [MDN: X-Frame-Options](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/X-Frame-Options)
|
||
- [MDN: CSP frame-ancestors](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors)
|
||
|