网站HTTP安全头配置HSTS、CSP
给 Nginx 站点加上 HTTP 安全响应头,能明显减少 XSS、点击劫持和中间人窃听风险。
本文以最常用的 add_header 指令为例,带你在本机或宝塔面板中完成 HSTS、CSP、X-XSS-Protection 等全套配置,并用 curl 验证返回结果。
内容不依赖特定版本,适用于目前主流的 Nginx 稳定版。
改配置前,先定位 Nginx 站点文件
正式动手前,先确认你要改的文件路径,避免改错全局配置导致整站异常。
典型的 Nginx 部署环境中,主配置位于 /etc/nginx/nginx.conf,虚拟站点通常放在 /etc/nginx/conf.d/ 或 /etc/nginx/sites-enabled/ 目录。
如果你用的是宝塔面板,可以打开“网站 → 设置 → 配置文件”直接编辑当前站点配置。
无论使用哪种方式,修改前都建议先备份:
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
# 如果是站点单独配置文件,则替换为实际路径,例如:
# cp /etc/nginx/conf.d/example.com.conf /etc/nginx/conf.d/example.com.conf.bak
备份完成后,再用命令确认配置语法是否正常:
nginx -t
看到 syntax is ok 和 test is successful 后再继续下一步。
核心配置:写入全套 HTTP 安全响应头
打开目标站点的 server 配置块,在 server_name 之后、location 之前添加以下代码:
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline';" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
这些指令的作用分别如下:
X-XSS-Protection:提示旧版浏览器启用反射型 XSS 过滤。现代 Chrome 和 Edge 已移除该机制,保留此项主要是兼容老浏览器。X-Content-Type-Options:禁止浏览器对响应内容做 MIME 类型猜测,降低类型混淆攻击风险。X-Frame-Options:设置SAMEORIGIN后,页面只允许被同源站点使用 iframe 嵌套,防止点击劫持。Strict-Transport-Security:也就是 HSTS,通知浏览器只能通过 HTTPS 访问该站点。max-age=31536000表示有效期为一年,includeSubDomains表示子域名同样生效。Content-Security-Policy:CSP 策略,用来限制页面可以加载的脚本、图片、样式等资源来源。上面给的只是基础版,线上使用需要根据站点的实际资源域名调整。Referrer-Policy:控制浏览器发送 Referrer 的时机,减少敏感信息泄露。
保存后先执行 nginx -t,再重新加载配置:
nginx -s reload
宝塔用户点击配置文件右上角的“保存”后,如果弹出重载提示,确认重载即可。
最容易踩的坑:add_header 继承与 HSTS 放置位置
新手配置时常遇到“明明写了 add_header,浏览器却没生效”的情况。
绝大多数原因出在 Nginx 的继承规则上。
如果当前 server 或 location 块内出现了任意一条 add_header,上层配置中的所有 add_header 都会失效。 这是一个“要么全部继承,要么全部丢失”的机制。
因此建议把所有响应头统一集中在 server 块写入,不要在 location 中单独写 add_header,除非你明确知道自己在做什么。
另一个常见错误是:把 HSTS 写在监听 80 端口的 server 块中。
HTTP 明文响应中的 HSTS 会被浏览器忽略,正确做法是只在 443 端口的 HTTPS server 块中添加。
如果你的 HTTPS 配置是通过跳转实现的,那么 HSTS 应放在最终处理 HTTPS 请求的那个 server 块里。