# 安全响应头配置指南

本文档说明如何在生产环境中配置安全响应头，防止点击劫持等安全攻击。

## 已实施的安全措施

### 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)

