网站安全头部配置指南: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'"

注意 Nginx 的 add_header 默认只在 200/201/204/206/301/302/304/307/308 这类“成功响应”上生效,加 always 才能覆盖 404、500 等错误页——而错误页恰恰是攻击者常探测的地方;Apache 的 Header always set 同理。另一个常见问题是只配了主站、没配子域名,导致 HSTS 覆盖不全。

如果用了 CDN 或云负载均衡(如 Cloudflare),安全头部最好在源站和边缘各配一遍:源站保证直连安全,边缘层用“响应头修改”规则统一兜底,一处改、全局生效。

三、验证安全头部

在线工具

  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'

一个真实案例

2024 年一家电商站的头像上传接口没设 X-Content-Type-Options: nosniff,攻击者上传了一个伪装成图片的 HTML,把钓鱼脚本嵌进去,访问者浏览器按 MIME 嗅探把它当页面渲染,会话 cookie 险些被窃取——修复只花了一行配置。类似地,缺失 X-Frame-Options 的站点可能被第三方页面用 iframe 包裹,诱导用户在不知情的情况下点击“授权”,也就是经典的点击劫持。安全头部挡不住所有攻击,但能把一大批常见的浏览器侧攻击拦在门外。

四、常见问题

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

CSP 报告怎么用

上线前建议先开 Content-Security-Policy-Report-Only 配合报告端点(report-urireport-to),跑一两周收集真实违规记录,再逐条放宽或修正,最后切到强制模式。盲目上严格策略、发现页面白屏再回滚,是最常见的翻车方式。

X-XSS-Protection 还需要吗

X-XSS-Protection: 1; mode=block 是老一代浏览器的产物,现代浏览器已将其废弃(Chrome 甚至专门引入了 X-XSS-Protection: 0 来关闭它),真正的 XSS 防护要交给 CSP。保留这一行主要是兼容性考虑,不必依赖它。

CSP 里用 nonce 还是 hash

内联脚本(inline script)比较麻烦:'unsafe-inline' 会整体放开,等于削弱 CSP。更精细的做法是用 nonce(一次性随机值)或 SRI hash 放行特定脚本。例如给 <script nonce="abc123"> 配上 script-src 'self' 'nonce-abc123',每次响应更换 nonce,攻击者无法预判,也无法复用旧值注入。

五、总结

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

参考:OWASP 安全头部速查表 https://owasp.org/www-project-secure-headers/ ;MDN 关于 CSP https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP ;HSTS preload https://hstspreload.org/