深入掌握Chrome DevTools Security面板实战技巧

技术晓萌 工具 阅读 2,073
赞 14 收藏
二维码
手机扫码查看
反馈

先看效果,再看代码

说实话,我之前一直没怎么正经用过浏览器的 Security 面板。平时调试基本靠 Network 看接口、Console 打日志、Elements 改 DOM。直到上周线上一个 HTTPS 混合内容警告把我坑惨了——用户打不开上传组件,排查半天才发现是某个 script 被自动降级成 HTTP 加载了。

深入掌握Chrome DevTools Security面板实战技巧

那次之后我决定把 Security 面板彻底摸一遍。结果发现这玩意儿其实贼实用,尤其是上线前做一次完整安全检查,能提前避掉一堆坑。

直接上最常用的场景:检测页面是否完全走 HTTPS。打开 DevTools → Security 标签页,刷新页面,你会看到类似这样的信息:

Security
  Overview: Connection secure
  Certificate: Valid
  Resources loaded via HTTPS: 100%
  Mixed content: None detected

但如果页面里有 HTTP 资源,就会变成这样:

Mixed content: Yes (1 blocked, 2 warnings)
  http://jztheme.com/static/js/legacy.js — blocked
  http://jztheme.com/assets/img/icon.png — insecure image

注意那个 blockedwarning 的区别:脚本类资源(JS/CSS)如果走 HTTP,会被现代浏览器直接拦截;图片、iframe 这种可能只是黄标提示,但依然存在风险。

这个场景最好用

我最近在做一个老系统迁移项目,原站用了大量内网地址和自定义证书。开发阶段根本没法保证 HTTPS,但又要让前端跑起来。这时候 Security 面板就成了我的“信任开关”指南。

比如访问一个带自签名证书的测试环境:https://test.jztheme.com:8081,页面会白屏,提示 NET::ERR_CERT_INVALID。常规操作是点高级→继续前往,但这对自动化测试或 CI 环境不现实。

解决方案分两步:

  1. 在 Chrome 地址栏输入 thisisunsafe(没错,就是连协议都不用输),页面会自动刷新并临时信任该证书
  2. 回到 Security 面板,点击右上角的“View certificate”,导出证书用于后续配置

虽然这不是长期方案,但在本地联调时亲测有效。别问我怎么知道的,折腾了整整一下午才从同事那偷学到这一招。

核心代码就这几行

当然,真正想根治问题还得改代码。最常见的混合内容问题来自动态拼接 URL。比如这段烂代码我就写过:

function loadScript(module) {
  const isProd = location.hostname === 'jztheme.com';
  const baseUrl = isProd ? 'https://' : 'http://';
  const script = document.createElement('script');
  script.src = ${baseUrl}jztheme.com/plugins/${module}.js;
  document.head.appendChild(script);
}

看起来逻辑没问题,但一旦页面被代理到 HTTPS(比如 Nginx 反向代理),而判断条件又只看 hostname,就会导致实际运行在 HTTPS 下却加载了 HTTP 资源——完美触发混合内容拦截。

改进方式很简单:用协议相对路径或者直接省略协议。

// 方式一:双斜杠开头(推荐)
script.src = '//jztheme.com/plugins/${module}.js';

// 方式二:直接用 HTTPS(更安全)
script.src = 'https://jztheme.com/plugins/${module}.js';

别小看这个改动,上线后 Security 面板里的“Mixed content”直接从 5 条降到 0。

高级技巧:强制 HTTPS + HSTS 检查

如果你的服务已经全面启用 HTTPS,建议加上 HSTS 响应头。这能让浏览器强制使用加密连接,哪怕用户手动输 HTTP 也会被重定向。

Nginx 配置示例:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

配置完后,在 Security 面板能看到明确提示:

HSTS: Enabled (max-age=31536000)
HSTS includes subdomains: Yes

这里注意下我踩过坑的地方:HSTS 的 max-age 一旦设置,浏览器会在有效期内记住这个规则,即使你后面把 header 删了也没用。所以开发阶段千万别在本地启 HSTS,否则清理缓存都救不了你,只能等时间过期或者手动去 chrome://net-internals/#hsts 清除。

调试 WebSocket 安全问题

很多人不知道 Security 面板还能看 ws/wss 的安全状态。我们有个实时通信模块用了 WebSocket,之前一直用 ws:// 测试,上线切 wss 后发现连接失败。

通过 Security 面板发现原因是证书域名不匹配:后端用的是 *.api.jztheme.com 泛域名证书,但我们连接的是 ws://realtime.jztheme.com,不在 SAN 列表里。

修复方法有两个:

  • 更新证书,把 realtime.jztheme.com 加进 SAN
  • 前端改用 wss://gateway.jztheme.com 并走反向代理

最终选了第二种,因为成本低且可控。改完后在面板里能看到:

Connection: Secure (TLS 1.3)
Protocol: WSS
Certificate: Valid

多说一句,WebSocket 的错误通常不会出现在 Console,必须主动去看 Security 和 Network 面板才能定位。

踩坑提醒:这三点一定注意

以下是我在实战中总结的三个最容易翻车的点,每一条都是拿线上事故换来的教训。

第一,iframe 嵌套第三方页面时的安全警告

我们有个管理后台要嵌入外部报表系统,用 iframe 包了一下。结果 Security 面板报了一堆“insecure passive content”。原因是对方站点虽然是 HTTPS,但某些静态资源用了 HTTP。解决不了对方的问题,我们只能加个中间页做代理转发,自己补全 SSL。

第二,Service Worker 缓存了 HTTP 资源

PWA 项目里,SW 一旦缓存了非安全资源,后续即使主站升级 HTTPS,这些资源还是会从缓存加载,导致 Security 面板持续报警。建议在 SW 安装阶段就做协议校验:

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open('v1').then(cache => {
      return fetch('/manifest.json')
        .then(res => res.json())
        .then(manifest => {
          const validResources = manifest.assets.filter(asset =>
            asset.url.startsWith('https://') || asset.url.startsWith('/')
          );
          return cache.addAll(validResources);
        });
    })
  );
});

第三,开发服务器热更新走的是 HTTP

很多本地开发服务器(webpack-dev-server/vite)默认用 HTTP 提供 HMR 功能。当你在 HTTPS 页面引入本地脚本时,就会触发混合内容拦截。解决方案是给 dev server 配 HTTPS:

// vite.config.js
export default {
  server: {
    https: true,
    host: 'localhost'
  }
}

启动后访问 https://localhost:3000 就不会再被 Security 面板红标警告了。

这个技巧的拓展用法还有很多,后续会继续分享这类博客

以上是我个人踩坑后的总结,希望对你有帮助。Security 面板看似冷门,其实关键时刻能救命。特别是上线前跑一遍检查,比用户反馈后再修要体面得多。

顺带提一句,Chrome 最近还加了个“Safety Check”功能(设置里能找到),可以批量扫描书签、密码、扩展的安全性,配合 Security 面板一起用,算是前端+用户侧双重保障了。

这个技巧的拓展用法还有很多,比如结合 CSP 报告分析、预检证书过期时间等等,后续会继续分享这类实战型博客。有更优的实现方式欢迎评论区交流。

本文章不代表JZTHEME立场,仅为作者个人观点 / 研究心得 / 经验分享,旨在交流探讨,供读者参考。
发表评论

暂无评论