场景与目标
业务已经部署 HTTPS,浏览器地址栏却仍提示“不安全”;或者控制台不断出现 Mixed Content 拦截,页面脚本被 CSP 拒绝执行,导致样式丢失、功能白屏。很多团队第一反应是检查 SSL 证书,但证书有效并不等于安全基线完整。
现代浏览器会综合判断 TLS 配置、资源加载方式以及 HTTP 安全响应头。缺失 Strict-Transport-Security、Content-Security-Policy 等响应头时,浏览器可能采取更保守的策略,从而触发“不安全”提示或拦截正常资源。
本文从工程实践角度,梳理“网站不安全”与安全响应头之间的关系,重点讨论 HSTS、CSP 的配置思路,并给出在阿里云接入层、边缘层和源站层的取舍与验证方法。目标是让读者能够定位问题、选择注入层级、完成配置并验证效果。
前置条件/环境
开始前,建议确认以下条件:
- HTTPS 已就绪:域名已完成 HTTPS 改造,证书已签发并部署到源站、ALB 或 CDN/DCDN。若使用阿里云 SSL 证书服务,需确认证书已签发且与目标域名匹配。
- 接入层明确:知道流量经过源站 Nginx、应用型负载均衡 ALB,还是内容分发网络 CDN/全站加速 DCDN。不同层级的响应头注入能力和生效范围不同。
- 权限与地域:本文以华东1(杭州)地域的 ALB 为例。操作者需具备相应 RAM 权限,例如 ALB 管理权限;具体权限策略、支持地域、实例版本和可配置字段,请以控制台和阿里云官方文档为准。
- 计费确认:ALB 可能涉及实例费、LCU 等计费项;CDN/DCDN 可能涉及流量、带宽或请求数费用;SSL 证书服务也可能产生证书费用。实际计费项和价格请以阿里云计费文档和控制台为准。
- 测试环境:准备与生产隔离的测试域名或测试环境。HSTS 和 CSP 都可能影响线上访问,不建议直接在生产环境一次性启用严格策略。
架构或方案选择
安全响应头的注入位置决定了维护成本和生效范围。常见有三层:
- 源站层,如 Nginx、Tomcat 或应用网关
- 优势:控制粒度最细,可以针对不同 URI、不同应用下发不同 CSP。
- 劣势:多节点维护成本高,经过 CDN 时可能被边缘节点覆盖或丢失。
- 接入层,如应用型负载均衡 ALB
- 优势:统一收口,无需修改业务代码,适合全局安全基线。
- 劣势:难以感知具体业务的细粒度差异,例如不同页面需要不同 CSP。
- 边缘层,如 CDN/DCDN
- 优势:全局生效,适合静态资源安全加固,就近响应。
- 劣势:动态请求回源时,若缓存或回源规则配置不当,动态安全策略可能不符合预期。具体自定义响应头能力以对应产品控制台和官方文档为准。
架构建议:全局通用基线,如 HSTS、X-Content-Type-Options、X-Frame-Options,优先在 ALB 或 CDN/DCDN 统一配置;业务强相关的 CSP,建议在源站或应用网关层按应用配置。无论选哪一层,都要遵循“单一真相源”原则:同一个响应头只在一层下发,避免重复。
实施步骤
步骤一:现状诊断
修改配置前,先确认当前响应头缺失情况。本地终端执行:
curl -I -k https://your-domain.com
重点检查:
Strict-Transport-SecurityContent-Security-PolicyX-Content-Type-OptionsX-Frame-OptionsReferrer-Policy
同时观察浏览器开发者工具的 Security 和 Console 面板,确认是否存在 Mixed Content、CSP 拦截或证书告警。
步骤二:配置 HSTS,但只选一层
HSTS 用于告知浏览器在指定时间内必须通过 HTTPS 访问该域名,可显著降低 HTTP 到 HTTPS 重定向劫持和降级攻击风险。
配置时请二选一:
- 如果流量统一经过 ALB,建议在 ALB 的 HTTPS 监听或转发规则中配置自定义响应头,源站 Nginx 不要再重复下发。
- 如果源站直连且没有统一接入层,可以在 Nginx 的 HTTPS server 块中配置。
Nginx 示例:
server {
listen 443 ssl;
server_name your-domain.com;
# 仅当未在 ALB/CDN 层配置 HSTS 时启用
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}
ALB 配置思路:
登录阿里云控制台,进入 ALB 实例,找到目标 HTTPS 监听或转发规则,在自定义响应头中新增:
- Header:
Strict-Transport-Security - Value:
max-age=31536000; includeSubDomains
不同地域、实例版本和控制台入口可能存在差异,具体支持情况以控制台和官方文档为准。若后续计划加入 preload,需评估子域名 HTTPS 覆盖情况和撤回成本,不建议初期直接启用。
步骤三:配置 CSP,先观察再阻断
CSP 是防御 XSS 和数据注入的重要机制。需要注意:CSP 默认会阻断内联脚本和 eval 等动态执行。如果业务依赖内联脚本或动态执行,需要通过 nonce 或 hash 放行;显式加入 unsafe-inline、unsafe-eval 可以放行,但会显著削弱 XSS 防护,不建议在生产环境长期使用。
工程化建议:先使用 Content-Security-Policy-Report-Only 观察违规,不直接阻断。
Nginx Report-Only 示例:
# 仅上报违规,不阻断资源加载
add_header Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self' https://trusted.example.com; style-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'; report-uri /csp-report-endpoint;" always;
观察一段时间后,再逐步切换为 Content-Security-Policy。若必须支持内联脚本,优先由应用层生成随机 nonce,而不是使用 unsafe-inline。nonce 需要每次响应不同,通常由后端模板或应用框架下发,Nginx 静态配置无法为每个请求生成唯一值。
步骤四:补充辅助安全响应头
除 HSTS 和 CSP,还建议配置:
X-Content-Type-Options: nosniff:禁止浏览器猜测 MIME 类型。X-Frame-Options: SAMEORIGIN:限制页面被同源嵌套,缓解点击劫持。Referrer-Policy: strict-origin-when-cross-origin:控制 Referer 发送策略,保护用户隐私。
如果源站和接入层同时配置相同响应头,可能出现重复。重复的 X-Frame-Options 可能导致行为不一致或被部分浏览器忽略,建议只在一层下发。
关键配置/代码
以下是一个适用于 Nginx 源站的安全响应头模板。若 HSTS 已在 ALB 或 CDN/DCDN 配置,请删除 HSTS 行,避免重复。
# 基础安全响应头
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# 若未在 ALB/CDN 层配置 HSTS,再启用此行
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# 生产 CSP 示例:不包含 unsafe-inline / unsafe-eval
# 若业务依赖内联脚本,请改用 nonce/hash,而不是长期使用 unsafe-inline
add_header Content-Security-Policy "default-src 'self'; img-src 'self' data: https:; script-src 'self' https://trusted.example.com; style-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'" always;
说明:always 参数确保在 4xx、5xx 响应中也下发安全头。以上配置中的 trusted.example.com 需替换为实际可信源。若临时兼容旧业务而加入 unsafe-inline 或 unsafe-eval,应明确记录风险和退出计划。
验证结果
配置完成后,按以下方式验证:
命令行验证
curl -I https://your-domain.com确认目标 Header 均已返回,且不存在重复的
Strict-Transport-Security或X-Frame-Options。浏览器验证
打开 Chrome 开发者工具,查看 Security 面板是否有 Mixed Content 或证书告警;查看 Console 是否有 CSP 拦截日志,例如Refused to load the script、Refused to apply style。公开扫描工具
可使用 Mozilla Observatory、SecurityHeaders.com 等公开工具扫描安全头。不同工具规则不同,建议关注其提示的缺失项和风险项,而不是只看单一评分。多子域名验证
若 HSTS 包含includeSubDomains,需验证所有子域名均支持 HTTPS,避免老旧测试域名无法访问。
成本、性能或安全注意事项
HSTS 的不可逆风险
一旦启用includeSubDomains,所有子域名都必须支持 HTTPS。若计划加入浏览器 Preload List,撤回流程较长。建议先在非核心子域名测试,初期使用较短max-age,例如 300 秒,确认无误后再逐步增加。CSP 的业务中断风险
CSP 默认阻断内联脚本和eval等动态执行。若业务依赖这些能力,应使用nonce或hash放行。显式加入unsafe-inline、unsafe-eval虽然能快速兼容,但会削弱 XSS 防护,不建议在生产长期使用。重复响应头问题
ALB、CDN/DCDN 和 Nginx 同时下发相同安全头时,可能出现重复字段。重复的X-Frame-Options可能导致行为不一致或被部分浏览器忽略。建议明确单一配置层,其他层保持透传或移除。性能与带宽
安全响应头会增加响应包体积。CSP 策略较长时,在海量并发下可能产生额外下行带宽消耗,但通常影响有限。建议在保证安全的前提下精简策略。云产品前提
ALB 的自定义响应头能力、CDN/DCDN 的配置入口、SSL 证书部署方式,均可能受地域、实例版本、权限和计费类型影响。操作前请以控制台和阿里云官方文档为准。
常见问题
Q1:配置 CSP 后页面样式丢失或第三方 JS 失效,如何排查?
打开浏览器控制台,查找 Refused to apply style 或 Refused to load the script 等报错。根据被拦截资源的域名或内联脚本位置,优先通过 nonce、hash 或白名单域名放行。不要直接把 unsafe-inline 加入生产策略。
Q2:HSTS 配置错误导致部分用户无法访问,如何紧急回退?
HSTS 依赖浏览器缓存,服务端无法立即撤销。若 max-age 过长,只能引导用户清除浏览器缓存,或在 chrome://net-internals/#hsts 中删除对应域名。因此初期测试应使用较短 max-age,确认子域名覆盖完整后再延长。
Q3:ALB 和 Nginx 同时配置了相同安全响应头,会冲突吗?
通常不会直接冲突,但可能出现重复 Header。重复的 X-Frame-Options 可能导致行为不一致或被部分浏览器忽略。建议遵循“单一真相源”,选定 ALB、CDN/DCDN 或 Nginx 其中一层配置,其他层不要重复下发。
总结
浏览器提示“不安全”并不总是证书问题,也可能是安全响应头缺失或配置不当。通过合理配置 HSTS、CSP、X-Content-Type-Options、X-Frame-Options 和 Referrer-Policy,可以从协议层和内容层提升 HTTPS 安全水位。
落地时建议先诊断现状,再选择统一接入层或源站层作为单一配置点;CSP 先以 Report-Only 观察,HSTS 先用短 max-age 灰度。涉及阿里云 SSL 证书服务、ALB、CDN/DCDN 时,务必结合账号权限、地域、版本和计费前提验证,具体能力以控制台和官方文档为准。