Google Chrome 访问 Pay Deposit 页面提示 insecure
结论
这是典型的 Mixed Content(混合内容) 问题。Pay Deposit 页面通过 HTTPS 打开,但表单、脚本、iframe、弹窗地址或某次重定向仍在访问 HTTP URL。Chrome 阻止请求后,支付流程无法继续,页面因此只显示主菜单或空白区域。
报错中最值得关注的是:
http://linkurl/404/
不要只检查页面直接引用的两个 include 文件,还要查清支付请求为什么最终进入 HTTP 的 /404/。原因可能是支付地址错误、相对路径解析异常、HTTP 重定向,或者站点的 404 错误处理程序把 HTTPS 请求降级成了 HTTP。
排查步骤
1. 用 Chrome DevTools 找出第一个异常请求
打开开发者工具,进入 Network 面板:
- 勾选 Preserve log。
- 清空现有记录。
- 重新执行 enrollment,然后点击 Pay Deposit。
- 搜索
http://、404,或者筛选状态码为3xx、4xx的请求。 - 查看异常请求的 Initiator、Headers 和重定向链。
需要确认:
- 最初请求的 URL;
- 发起请求的页面或脚本;
- 请求是否先访问 HTTPS,随后被
Location响应头重定向到 HTTP; /404/是直接请求的地址,还是服务器处理错误时跳转过去的。
Console 中的 mixed-content 报错通常只显示最终被阻止的 URL。Network 面板中的发起者和重定向链更适合追查问题源头。
2. 检查支付流程中的所有 URL
除了 <script> 和 <link>,还要检查这些位置:
<form action="http://example.com/pay">
<iframe src="http://example.com/pay">
<script src="http://example.com/payment.js"></script>
<link rel="stylesheet" href="http://example.com/payment.css">
<img src="http://example.com/logo.png">
<base href="http://example.com/">
JavaScript 也可能动态发起不安全请求:
window.open("http://example.com/pay");
location.href = "http://example.com/pay";
fetch("http://example.com/api/deposit");
如果支付按钮位于弹窗中,尤其要检查:
window.open()的目标地址;- 表单的
action和target; - iframe 的
src; - AJAX 请求返回的跳转地址;
- 服务端生成的支付 URL;
<base>标签是否把相对路径解析成了 HTTP。
3. 将内部地址改为 HTTPS 或站内相对地址
同一站点内的资源优先使用根相对路径:
<form action="/pay/deposit" method="post">
<!-- payment fields -->
</form>
<script src="/assets/payment.js"></script>
<link rel="stylesheet" href="/assets/payment.css">
必须使用绝对地址时,明确指定 HTTPS:
<form action="https://example.com/pay/deposit" method="post">
JavaScript 中也应采用相同方式:
window.open("/pay/deposit", "payDeposit");
不建议把协议相对 URL 作为长期修复方案:
<script src="//example.com/payment.js"></script>
这种地址通常会继承当前页面的协议,但明确使用 HTTPS 或站内相对路径更便于审计,也不会在非预期环境中回落到 HTTP。
4. 修复重定向和 404 页面配置
如果初始地址已经使用 HTTPS,但响应中出现:
Location: http://example.com/404/
问题出在服务端,而不是 HTML include 文件。重定向也应保持 HTTPS:
Location: https://example.com/404/
通常更合适的做法是直接返回正确的 404 状态和错误页面,不再跳转到另一个 URL:
HTTP/1.1 404 Not Found
Content-Type: text/html; charset=utf-8
同时检查:
- Web 服务器的 rewrite/redirect 规则;
- 应用中的 canonical URL、base URL 或 site URL 配置;
- 反向代理传递的原始协议;
- 404、登录和支付失败处理代码;
- 支付服务的回调地址和返回地址。
如果应用部署在负载均衡器或反向代理之后,外部连接可能使用 HTTPS,而应用服务器看到的却是 HTTP,应用便可能错误地生成 http:// URL。此时需要正确传递并验证原始协议,例如:
X-Forwarded-Proto: https
信任代理的具体配置取决于所使用的 Web 框架。不要在未限制可信代理来源时,直接信任客户端提供的 X-Forwarded-Proto。
5. 确认第三方支付服务支持 HTTPS
如果 http://linkurl 属于第三方支付服务,需要确认该服务提供有效的 HTTPS 接口。不能直接把 URL 中的 http: 改成 https:,因为对方服务器可能没有配置 HTTPS、有效证书或对应路由。
如果第三方资源没有 HTTPS 版本,就不能安全地嵌入 HTTPS 支付页面。可以选择:
- 使用该服务提供的 HTTPS 地址;
- 升级支付接口;
- 更换支持 HTTPS 的支付服务;
- 在支付服务明确支持的情况下,使用其官方托管支付页流程。
关闭 Chrome 的安全设置不能解决生产环境中的问题,只会在本机掩盖风险,其他用户仍会遇到请求被阻止的情况。
可增加的安全配置
修复所有 HTTP 引用后,可以添加 Content Security Policy,用于发现遗漏的资源或尝试将其升级:
Content-Security-Policy: upgrade-insecure-requests; block-all-mixed-content
也可以先启用仅报告模式进行观察,以免立即影响线上功能:
Content-Security-Policy-Report-Only: upgrade-insecure-requests
upgrade-insecure-requests 会尝试把 HTTP 子资源升级为 HTTPS,但无法处理以下问题:
- 目标服务器不支持 HTTPS;
- HTTPS 路径不存在;
- 证书无效;
- 应用在重定向后再次降级到 HTTP;
- URL 指向错误路径,并最终进入
/404/。
因此,CSP 只能作为补充,不能代替修复实际链接和服务端配置。
确认整个站点能够稳定通过 HTTPS 工作后,还可以考虑启用 HSTS:
Strict-Transport-Security: max-age=31536000; includeSubDomains
启用 includeSubDomains 前,需要确认所有子域名都支持 HTTPS,否则可能导致部分子域名无法访问。
为什么其他浏览器正常
其他浏览器能显示页面,不代表页面配置没有问题。不同浏览器和不同版本对 mixed content 的拦截策略可能不同。旧浏览器可能继续加载不安全内容,而 Chrome 会阻止影响页面逻辑的脚本、iframe、表单或请求。
支付页面涉及账户和交易数据,不能依赖浏览器放宽安全限制。修复后的标准应该是:从点击 Pay Deposit 按钮开始,直到支付页面、接口请求、错误处理和重定向结束,整个请求链都使用有效的 HTTPS,并且不再生成任何 http:// 子资源。
备注:内容仅供参考。
