Security面板里为什么显示混合内容警告?
我在本地开发一个 HTTPS 网站,但 Chrome DevTools 的 Security 面板一直提示“混合内容”警告,明明我所有资源都用的是相对路径啊。
我试过把图片和接口都改成 https,但还是报错。控制台没报错,但 Security 面板就是标红,搞得我很困惑。下面是我加载图片的代码:
const img = new Image();
img.src = '/assets/logo.png'; // 本地开发环境是 https://localhost:3000
document.body.appendChild(img);
Chrome 的 Security 面板对证书检查很敏感。如果你用的是自签名证书或者所谓 的 "localhost" 内部证书,Chrome 会认为这个 HTTPS 根本不安全,相当于整个页面被标记为基础不安全模式,然后它就会把页面内所有资源都当作"可能混合内容"来处理,即使你用的是相对路径。
你可以打开 Security 面板,点那个红色的警告,看看具体提示什么。如果证书不信任的话,应该会显示 "main tab is not secure" 之类的。
解决方案有几个:
一个是让 Chrome 信任你的自签名证书,把证书添加到系统受信任根证书列表。不过 Mac 上操作有点麻烦。
另一个更省事——在 Chrome 启动参数里加
--allow-insecure-localhost,这样 Chrome 就不会因为自签名证书为难你了。还有一种情况是,你的页面里是不是引了第三方脚本或者 iframe?比如一些 CDN 的资源、统计代码之类的,这些很容易被忽略,但它们如果走 HTTP 就会触发混合内容警告。检查一下 network 面板,看看有没有哪个请求是 http 开头的。
你本地开发用的是什么?http-server -S 还是 webpack dev server?这类工具的证书配置有时候挺坑的。
先说一个很多人容易忽略的点:检查一下你的页面里有没有设置
标签。如果写了,那相对路径全都会按这个 base 来解析,浏览器可不管你当前页面是 https 还是 http。如果没有 base 标签,打开 Network 面板,看看 logo.png 实际请求的 URL 到底是什么,看是不是真的走了 https。还有一种情况是 Chrome 扩展搞的鬼,有些插件会注入 http 资源到页面里,这种情况下 Security 面板也会报警,但控制台不会报错。
如果以上都不是,你可以试试把资源路径改成完整的带协议的 URL,比如
https://localhost:3000/assets/logo.png,虽然丑但能彻底排除协议问题。对了,你确定报警的就是这个 logo.png?有些时候是页面的其他资源(比如 iframe、websocket 连接)导致的,Security 面板显示的上下文需要看清楚。