Selenium自动化测试绕过Chrome证书错误弹窗的完整指南

发布时间:2026/10/18 11:40:40
Selenium自动化测试绕过Chrome证书错误弹窗的完整指南 如果你维护过一段时间自动化测试脚本大概率被 Chrome 那个写着“您的连接不是私密连接”的深灰色警告页卡过。脚本停在那个页面上click 找不到元素等待超时任务挂掉日志里只有一行孤零零的 SSL 错误。我早年在某公司维护端到端回归用例时这个问题几乎每周都要跳出来一次尤其是在访问测试环境、预发布环境或者内网搭建的服务时浏览器动不动就给你脸色看。这个问题的本质是浏览器做证书链校验时发现目标站点的 HTTPS 证书不可信于是它宁可拒绝访问也不放行。对普通用户来说这层保护是对的但对 Selenium 自动化来说它就是一个纯粹的“坑”测试环境本来就是用自签名证书或过期证书搭起来的脚本不可能每次都跑过去手动点一下“仍然继续”。所以我们需要在启动浏览器时从 WebDriver 层面和浏览器进程层面把这道“安全门”打开让测试脚本能顺畅地访问那些证书不规范的站点同时又不影响正常环境下的安全检查。这篇文章会把这个弹窗的成因、绕过它的几种方案、不同编程语言里的写法、以及我在实际项目中踩过的坑一次讲清楚。适合正在做 UI 自动化、接口自动化中需要调用浏览器页面的测试开发同学也适合刚接触 Selenium 但已经被证书错误折磨过的新手。1. 先弄清楚这个弹窗到底是谁在拦你1.1 浏览器做证书校验的三层逻辑Chrome 之所以弹出“您的连接不是私密连接”是因为它走完 TLS 握手之后对服务器返回的数字证书做了三层检查第一证书是否由受信任的根证书颁发机构签发第二证书是否过期第三访问的域名和证书里的域名是否匹配。任何一个环节出问题Chrome 都会直接终止页面加载并在地址栏下方或整页显示安全警告。举个例子你本地启动了一个前后端联调服务挂的是自签名证书。浏览器打开时看到的错误类型往往是NET::ERR_CERT_AUTHORITY_INVALID意思是没有找到能追溯到受信根 CA 的证书链。如果证书已经过期了出现的是NET::ERR_CERT_DATE_INVALID。如果证书是给dev.example.com签的你却用 IP192.168.1.10去访问就会报NET::ERR_CERT_COMMON_NAME_INVALID。这三种错误虽然文字不同但在 Selenium 里表现都一样driver.get()停住后续任何元素操作都超时。从技术底层来说这个拦截是浏览器进程内部完成的和 WebDriver 协议本身没有直接关系。但 WebDriver 规范里专门为自动化场景提供了一个 capability 用来“接受不安全的证书”也就是acceptInsecureCerts。另外Chrome 也保留了一组命令行启动参数可以从浏览器进程层面直接关闭证书校验。理解了这一点后面所有方案就都串起来了要么走 Selenium 标准能力要么走浏览器启动参数要么两者一起上。1.2 为什么自动化测试环境里最容易触发生产环境的证书一般没问题因为公网站点都接入了正规 CA。但测试环境基本都处于“能跑就行”的状态有的人直接用openssl req -x509生成一张十年期的自签证书有的人在服务器上把 HTTPS 配置的证书链少贴了一节有的甚至把前一年的过期证书原封不动搬过来用。内网 IP 访问、临时域名、随手写的CN字段这些都是自动化用例的定时炸弹。还有一个很容易被忽略的场景公司对内网流量做了 SSL 解密审计代理服务器会在中间替换证书。这种情况下浏览器看到的是代理机构签发的证书而这份证书没有安装到测试机器的系统信任库中于是访问任何 HTTPS 站点都会报证书错误。这种场景下即使你跳过了证书校验还会跟代理本身发生各种奇奇怪怪的交互问题我在后面排查章节里会单独说。说白了自动化测试跑得越多遇到这个弹窗的概率就越高。它不是偶发问题而是测试环境安全配置不完整时的一种”必然结果“。所以解决方案不能是“每次遇到就手工点一下继续”那样根本无法融入持续集成流水线。2. 方案一用 Selenium 标准能力绕过去2.1 acceptInsecureCerts 的用法与原理acceptInsecureCerts是 W3C WebDriver 规范中定义的一个标准 capability专门用来指示浏览器在会话内自动接受不安全的证书。在 Selenium 4 的 Python 版本里配置方式非常简单直接在Options对象上把属性置为Truefrom selenium import webdriver from selenium.webdriver.chrome.options import Options options Options() options.accept_insecure_certs True driver webdriver.Chrome(optionsoptions) driver.get(https://self-signed.dev.local)这段代码的底层逻辑是ChromeDriver 在创建新会话时会把acceptInsecureCerts转成 Chrome 内部的--ignore-certificate-errors开关并在会话生命周期内始终生效。它不像某些 hack 方案那样需要你在启动后再执行额外步骤而是从一开始就告诉浏览器“这个会话里有证书问题的站点也可以继续加载”。这个方案最明显的优势是写法干净、语义清晰。测试脚本阅读者一看就知道这个会话允许访问不安全证书而不会误以为你放弃了所有安全保护。而且它只作用于当前 WebDriver 会话不会全局修改浏览器的默认行为也不影响你在同一台机器上手动打开 Chrome 时的安全级别。2.2 实操完整的最小可运行示例光设置一个属性还不够真实项目中还需要处理浏览器驱动路径和隐式等待等问题。下面这个例子是典型的、可以直接运行的最小验证脚本import time from selenium import webdriver from selenium.webdriver.chrome.options import Options options Options() options.accept_insecure_certs True options.add_argument(--ignore-certificate-errors) driver webdriver.Chrome(optionsoptions) driver.implicitly_wait(10) try: driver.get(https://self-signed.dev.local) time.sleep(2) print(当前页面标题:, driver.title) print(当前页面URL:, driver.current_url) finally: driver.quit()注意这里我同时加了accept_insecure_certs和--ignore-certificate-errors。可能有人会觉得重复但我在实测中发现某些 Chrome 版本里只设置前者、在访问带 HSTS 头的站点时依然会被拦加上后者就稳了。既然两个参数不冲突为什么不在一次启动时都传进去代价接近于零收益是一致性大幅提升。这个脚本跑完后如果你发现标题能正常打印出来说明证书拦截已经被成功绕过。如果仍然停在错误页那就要看是不是 Chrome 版本太新、参数被策略限制的情况下面的章节会专门讲。3. 方案二Chrome 启动参数这把大杀器3.1 关键的启动参数组合与执行细节Chrome 有一组命令行参数可以在浏览器启动时直接修改安全策略。最核心的是--ignore-certificate-errors它会让 Chrome 忽略站点证书的所有错误包括过期、域名不匹配、证书链断裂等。但在较新的 Chrome 版本里Chrome 团队对命令行参数做了一些限制单独使用这个参数有时并不会生效。实操中的稳妥做法是再加一个--test-type--ignore-certificate-errors --test-type--test-type是 Chrome 内部用于测试模式的参数它告诉浏览器“当前这个进程是用作自动化测试的”因此可以放行那些日常模式下会被拒绝的实验性开关和敏感策略。两个参数组合使用能覆盖绝大多数证书错误场景哪怕目标是 HSTS 站点也会被强制忽略证书问题。这里要特别提醒一点--ignore-certificate-errors是全局性的“大杀器”它会关闭整个浏览器进程的证书校验能力。如果你在同一个 Chrome 会话里既要访问测试环境的自签名站点又要访问公网的真实站点那么公网站点也会跳过校验。对测试环境来说这不是问题但如果你在脚本里还要做支付流程、订单提交这类对安全要求很高的操作最好单独起一个测试专用的 Chrome 实例而不要直接在你日常浏览器配置上启动。3.2 各语言中的落地写法这个参数在 Python、Java、JavaScript 里写法不同但核心思路完全一致。这里把三个主流语言的示例都放一下方便不同技术栈的团队直接参考。Pythonfrom selenium import webdriver from selenium.webdriver.chrome.options import Options options Options() options.add_argument(--ignore-certificate-errors) options.add_argument(--test-type) driver webdriver.Chrome(optionsoptions)Javaimport org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.chrome.ChromeOptions; ChromeOptions options new ChromeOptions(); options.addArguments(--ignore-certificate-errors); options.addArguments(--test-type); WebDriver driver new ChromeDriver(options); driver.get(https://self-signed.dev.local);JavaScriptconst { Builder } require(selenium-webdriver); const chrome require(selenium-webdriver/chrome); let options new chrome.Options(); options.addArguments(--ignore-certificate-errors, --test-type); let driver new Builder() .forBrowser(chrome) .setChromeOptions(options) .build();除此之外还有一个偏“底层”的方式是直接调用 Chrome DevTools Protocol在会话建立后动态关闭证书校验driver.execute_cdp_cmd(Security.setIgnoreCertificateErrors, {ignore: True})这个方式适合你已经用driver.get()访问了一个页面、发现被拦截、然后又想临时放行的情况。不过它属于事后补救没有启动参数那么干净而且每次新会话都要重新执行一遍我的建议是把它当作调试技巧而不是常规方案。3.3 方案横向对比表方案原理层级是否支持远程会话是否影响全局推荐指数accept_insecure_certs TrueWebDriver 标准能力支持可随会话传递仅当前会话高--ignore-certificate-errorsChrome 进程启动参数仅本地启动时可指定整个浏览器进程中--ignore-certificate-errors --test-type启动参数测试模式仅本地启动时可指定整个浏览器进程高Security.setIgnoreCertificateErrorsCDP 底层协议支持当前页面会话中从表里能直观看出accept_insecure_certs在远程 WebDriver、Selenium Grid 场景中更占优势因为它属于会话级别的能力描述可以跨节点传递而命令行参数则更适合本地跑一个独立测试进程的情况。我个人的习惯是把它们组合使用既保证本地直接跑也保证上传到 CI 执行节点后有兜底。4. 特殊场景的补充打法4.1 HSTS 站点和 302 跳转劫持如果你的被测站点启用了 HSTSHTTP Strict Transport Security浏览器会强制使用 HTTPS并且不允许用户轻易“继续访问”因为 HSTS 的设计目标就是对抗 SSL 剥离攻击。这时候单独设置accept_insecure_certs大概率无效必须配合--ignore-certificate-errors才能让 Chrome 放弃 HSTS 检查。我在某次测试一个内部单点登录系统时就遇到过这种问题。登录入口本身是 HTTPS但页面里有一段302跳转把用户从https://转到http://的静态资源域名上然后再弹回来。这一来一回Chrome 直接拦截了后面的证书错误脚本就卡在“您的连接不是私密连接”的页面。最后我在启动参数里加了--ignore-certificate-errors和--test-type问题才真正解决。另外一个容易忽略的点是如果被测页面里嵌入了iframe或静态资源而这部分资源用的也是自签名证书那么即使主页面能被访问iframe里的内容也可能加载不出来。Selenium 的switch_to.frame()在切换到这些iframe时会直接报错。处理方式依然是靠全局参数或确认测试环境证书统一正确没有别的捷径。4.2 远程 WebDriver 和 Selenium Grid 环境下的传导问题在本地用ChromeDriver时启动参数非常直接。但如果你把测试跑在 Selenium Grid 或第三方云测平台上情况就不一样了。远程节点收到的不是本地的options.add_argument()而是一个 JSON Wire Protocol 里的 capabilities 描述。如果你只在远程节点本地的ChromeOptions里写了参数而创建请求时没有把它随 capabilities 一起发送那么远端浏览器根本不会加载这些参数。正确的做法是在创建远程会话时显式传入acceptInsecureCertsfrom selenium import webdriver from selenium.webdriver.chrome.options import Options options Options() options.accept_insecure_certs True # 远程 WebDriver / Grid 场景 driver webdriver.Remote( command_executorhttp://grid.example.com:4444/wd/hub, optionsoptions )同时在远端节点上最好也把系统级信任库配好否则即使 WebDriver 忽略了证书错误部分http请求仍可能被节点所在环境的代理截断。这个又回到了我在开头提到的“SSL 解密”场景。云测平台的浏览器进程通常是从预置镜像里拉起来的如果你没有权限修改远程节点的启动脚本优先保证acceptInsecureCerts能传上去是最可控的做法。4.3 更彻底的方案把测试环境证书装进系统信任库如果证书是团队内部自建的可以直接把根证书导出后安装到运行测试的机器或容器镜像的信任库中。这样浏览器和 WebDriver 都无需任何特殊参数访问自签名环境就像访问正式环境一样安全模型保持完整。在 Linux 容器里通常是这么做的cp self-signed-ca.crt /usr/local/share/ca-certificates/ update-ca-certificates实测下来这个方案的稳定性最高因为它解决的是证书“根因”而不是在浏览器层面对错误视而不见。缺点是需要维护镜像、更新证书周期如果测试环境隔三差五换一张证书运维成本就会变大。我建议保留这个方案作为小团队长期稳定跑的基线而把acceptInsecureCerts作为快速响应手段。5. 高频坑位排查速查表5.1 参数明明设了却不生效最典型的“坑”是你在Options里加了accept_insecure_certs True但脚本还是被证书错误页卡住。第一步要确认你用的 Selenium 版本。Selenium 3 和 Selenium 4 在Options的属性和参数传递方式上有差异旧接口的写法可能不会把 capability 正确传到 ChromeDriver。推荐先升级到 Selenium 4然后用driver.capabilities打印一下实际会话状态print(driver.capabilities.get(acceptInsecureCerts))如果输出是True说明 capability 已经传进去了问题多半出在 Chrome 版本对参数的限制上。这时候再叠加--ignore-certificate-errors --test-type启动参数通常能解决。如果输出是None或False那说明你的Options没有正确传递检查一下是不是用了Capabilities对象合并时覆盖了设置。5.2 代理、无头模式、版本冲突三类常见问题下面这张速查表基本覆盖了我在实际项目和社区帮人排查时遇到的高频问题现象常见原因处理方法设置了accept_insecure_certs仍在错误页Chrome 版本较新单参数被策略限制同时加--ignore-certificate-errors和--test-type无头模式下证书错误依旧headless模式参数传递方式不同显式添加--ignore-certificate-errors再验证--headlessnew语法访问 HTTPS 站点出现ERR_SSL_PROTOCOL_ERROR代理服务器介入但证书未安装配置代理信息、安装代理证书或在测试网络中禁用 SSL 解密Chrome 升级后脚本先前的处理失效浏览器版本与 ChromeDriver 版本不匹配用 webdriver-manager 自动匹配驱动版本远程 Grid 中参数无效未将 options 随远程会话一起传递改为webdriver.Remote(optionsoptions)并显式传 capability页面能访问但 iframe 资源加载失败内嵌资源仍是自签名证书用全局忽略参数或修复测试环境资源证书其中“Chrome 升级后脚本失效”这个问题的隐蔽性最强。Chrome 每隔几周就自动更新而 ChromeDriver 如果还是旧版两者版本不匹配时甚至不会正常启动浏览器表现出的症状五花八门。强烈建议在项目里接入 webdriver-manager 这类工具from selenium import webdriver from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager service Service(ChromeDriverManager().install()) driver webdriver.Chrome(serviceservice, optionsoptions)它会自动读取本机 Chrome 版本号并下载匹配的 ChromeDriver能少掉很多环境层面的麻烦。5.3 识别“是否还停留在错误页”的调试技巧最后分享一个调试小技巧Chrome 的证书错误页地址栏并不是正常网址而是chrome-error://chromewebdata/这种内部地址。所以你在脚本里可以通过判断driver.current_url快速识别是否被拦截def is_cert_error_page(driver): return driver.current_url.startswith(chrome-error://)如果判断为True再执行任何页面交互都没有意义应该直接刷新或重新driver.get()。搭配page_load_strategy eager使用可以避免页面在加载阶段长时间卡住让脚本能更快地进入后续等待逻辑。我在平时调试时也会把driver.current_url打印到日志里一旦发现被拦截日志里立刻能看到错误页地址不用去猜到底卡在哪一步。另外如果你需要在同一个会话里访问多个不同域名的测试站点而其中一个站点证书有问题那最好把证书处理放到启动阶段一次性解决而不是在脚本中途用 CDP 命令临时开启忽略。临时开启的忽略状态不会自动重置后续访问其他站点时可能会掩盖真正的证书问题排查起来更难。就我个人经验来说最稳的组合是启动时同时设置accept_insecure_certs和--ignore-certificate-errors --test-type然后配合 webdriver-manager 管好浏览器驱动版本再在脚本里加一个chrome-error://的判断兜底。这套方案在本地 Windows、macOS、Linux CI 上都验证过除了个别代理网络环境需要额外配置系统信任库之外几乎没有再被“您的连接不是私密连接”卡过。如果你也被这个弹窗折磨过不妨按这个顺序把代码过一遍大概率直接就能救回来。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询