网站安全头部配置指南:CSP / HSTS / X-Frame-Options 详解

HTTP 安全头部是浏览器端安全的第一道防线。通过配置正确的安全头部,可以有效防御 XSS、点击劫持、MIME 嗅探等攻击。安全头部配置简单、成本极低,但防御效果显著。

一、核心安全头部

1.1 Content-Security-Policy (CSP)

CSP 是防御 XSS 和注入攻击的最强武器。它告诉浏览器哪些来源的资源是可信的。

# Nginx 配置
add_header Content-Security-Policy "
    default-src 'self';
    script-src 'self' 'unsafe-inline' https://trusted-cdn.com;
    style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
    img-src 'self' data: https:;
    font-src 'self' https://fonts.gstatic.com;
    connect-src 'self' https://api.example.com;
    frame-src 'self';
    object-src 'none';
    base-uri 'self';
    form-action 'self';
" always;

CSP 指令详解

指令 控制内容 建议值
default-src 所有资源的默认来源 'self'
script-src JavaScript 来源 'self' 或特定 CDN
style-src CSS 来源 'self' 或特定 CDN
img-src 图片来源 'self' data: https:
connect-src API/XHR/Fetch 来源 'self' 或 API 域名
font-src 字体来源 'self' 或字体 CDN
frame-src iframe 来源 'self'
object-src Flash/Java 来源 'none'
base-uri <base> 标签 'self'
form-action 表单提交目标 'self'

CSP 部署策略

阶段 1:仅报告模式(观察是否有违规)
Content-Security-Policy-Report-Only: ...; report-uri /csp-report

阶段 2:宽松策略(逐步收紧)
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https:;

阶段 3:严格策略(去掉 unsafe-inline)
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted-cdn.com;

1.2 Strict-Transport-Security (HSTS)

HSTS 告诉浏览器始终使用 HTTPS 连接你的网站,即使用户输入 HTTP 地址。

# 初始配置(短时间,观察是否有问题)
add_header Strict-Transport-Security "max-age=3600; includeSubDomains" always;

# 生产配置(1 年)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

HSTS preload

将网站提交到 https://hstspreload.org 后,你的域名会被硬编码到浏览器中,即使用户从未访问过你的网站,浏览器也会使用 HTTPS

要求

  1. HSTS 头部必须设置 max-age 至少 31536000(1 年)
  2. 必须设置 includeSubDomains
  3. 网站必须完全通过 HTTPS 访问(无 HTTP 内容)

1.3 X-Frame-Options

防止点击劫持攻击,控制页面能否被嵌入 iframe。

# 拒绝被任何页面嵌入(推荐)
add_header X-Frame-Options "DENY" always;

# 仅允许同源页面嵌入
add_header X-Frame-Options "SAMEORIGIN" always;

注意:X-Frame-Options 的优先级高于 CSP 的 frame-ancestors。如果两者都设置,X-Frame-Options 规则优先。

1.4 X-Content-Type-Options

防止浏览器 MIME 类型嗅探攻击:

add_header X-Content-Type-Options "nosniff" always;

当设置为 nosniff 时,浏览器会严格遵循服务器返回的 Content-Type 头,不会自行猜测文件类型。这可以防止攻击者上传伪装成图片的 HTML 文件。

1.5 Referrer-Policy

控制 HTTP 请求中 Referer 头携带的信息量:

# 推荐:同源请求发送完整 Referer,跨域请求仅发送来源
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

可选值

行为
no-referrer 不发送 Referer
same-origin 仅同源请求发送
strict-origin 仅发送来源域名(HTTPS→HTTPS)
strict-origin-when-cross-origin 推荐:同源完整,跨域仅域名
unsafe-url 始终发送完整 URL(不推荐)

1.6 Permissions-Policy

控制浏览器 API 权限:

add_header Permissions-Policy "geolocation=(), microphone=(), camera=(), payment=()" always;

二、完整安全头部配置

Nginx 推荐配置

# /etc/nginx/conf.d/security-headers.conf
# 安全头部配置
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=(), payment=()" always;

# CSP - 根据您的网站实际情况调整
add_header Content-Security-Policy "
    default-src 'self';
    script-src 'self' 'unsafe-inline' https:;
    style-src 'self' 'unsafe-inline' https:;
    img-src 'self' data: https:;
    font-src 'self' https:;
    connect-src 'self' https:;
    frame-src 'self';
    object-src 'none';
    base-uri 'self';
    form-action 'self';
" always;

Apache 推荐配置

# .htaccess 或 httpd.conf
Header always set X-Frame-Options "DENY"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=(), payment=()"
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' data: https:; font-src 'self' https:; connect-src 'self' https:; frame-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'"

三、验证安全头部

在线工具

  1. Security Headers (https://securityheaders.com) - 评分制检测
  2. Mozilla Observatory (https://observatory.mozilla.org) - 全面安全评估
  3. CSP Evaluator (https://csp-evaluator.withgoogle.com) - CSP 规则评估

命令行检查

# 使用 curl 检查安全头部
curl -sI https://example.com | grep -i "security\|csp\|hsts\|frame"

# 示例输出
strict-transport-security: max-age=31536000; includeSubDomains
x-frame-options: DENY
x-content-type-options: nosniff
content-security-policy: default-src 'self'; script-src 'self'

四、常见问题

CSP 导致功能异常

CSP 过于严格可能导致某些功能失效:

问题:第三方脚本(如 Google Analytics)被阻止
解决:在 CSP 中添加第三方域名
script-src 'self' https://www.google-analytics.com https://www.googletagmanager.com;

HSTS 导致 HTTP 网站无法访问

如果在开发阶段错误启用了 HSTS,可能导致本地开发环境无法访问:

# Chrome 清除 HSTS
chrome://net-internals/#hsts
# 在 Domain 中输入域名,点击 Delete

五、总结

HTTP 安全头部是性价比最高的安全措施之一。只需在 Web 服务器配置中添加几行代码,就能防御多种常见攻击。建议逐步部署:首先添加 X-Frame-Options、X-Content-Type-Options 和 Referrer-Policy(这些基本不会影响现有功能),然后逐步部署 CSP 和 HSTS。使用 SecurityHeaders.com 检测评分,目标是达到 A 级或 A+ 级。