ChromeDriver ERR_SSL_PROTOCOL_ERROR despite --ignore-certifi



我正在尝试在本地主机(没有HTTPS)上使用Selenium和ChromeDriver运行集成测试。

Chrome 需要 https 证书,但从这个问题中我明白我可以使用 arg--ignore-certificate-errors来规避这一点

我还增加了我的能力acceptInsecureCerts,因为这似乎是适当的行动方案(文档)

chromedriver 的响应仍然不是我所期望的:

此站点无法提供安全连接应用发送无效响应。 ERR_SSL_PROTOCOL_ERROR

我的代码如下:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
# make options (principally to ignore certificate)
options = webdriver.ChromeOptions()
options.add_argument('--ignore-certificate-errors')
# add acceptInsecureCerts
capabilities = options.to_capabilities()
capabilities['acceptInsecureCerts'] = True
print(capabilities) # see below
driver = webdriver.Remote(
command_executor=SELENIUM_HUB,
desired_capabilities=capabilities
)
print(driver.__dict__) # see further below
app_login_url = 'http://app:8000/accounts/login/'
driver.get(app_login_url)

我的能力:

{'acceptInsecureCerts': True,
'browserName': 'chrome',
'goog:chromeOptions': {'args': ['--ignore-certificate-errors'],
'extensions': []},
'platform': 'ANY',
'version': ''}

这是我的驱动程序信息,看起来只考虑了acceptInsecureCerts参数:

{'_file_detector': <selenium.webdriver.remote.file_detector.LocalFileDetector object at 0x7fb42bde10f0>,
'_is_remote': True,
'_mobile': <selenium.webdriver.remote.mobile.Mobile object at 0x7fb42bb5e400>,
'_switch_to': <selenium.webdriver.remote.switch_to.SwitchTo object at 0x7fb42bdd4898>,
'capabilities': {'acceptInsecureCerts': True,
'acceptSslCerts': True,
'applicationCacheEnabled': False,
'browserConnectionEnabled': False,
'browserName': 'chrome',
'chrome': {'chromedriverVersion': '74.0.3729.6 '
'(255758eccf3d244491b8a1317aa76e1ce10d57e9-refs/branch-heads/3729@{#29})',
'userDataDir': '/tmp/.com.google.Chrome.vc1ZvB'},
'cssSelectorsEnabled': True,
'databaseEnabled': False,
'goog:chromeOptions': {'debuggerAddress': 'localhost:40815'},
'handlesAlerts': True,
'hasTouchScreen': False,
'javascriptEnabled': True,
'locationContextEnabled': True,
'mobileEmulationEnabled': False,
'nativeEvents': True,
'networkConnectionEnabled': False,
'pageLoadStrategy': 'normal',
'platform': 'Linux',
'proxy': {},
'rotatable': False,
'setWindowRect': True,
'strictFileInteractability': False,
'takesHeapSnapshot': True,
'takesScreenshot': True,
'timeouts': {'implicit': 0,
'pageLoad': 300000,
'script': 30000},
'unexpectedAlertBehaviour': 'ignore',
'version': '74.0.3729.169',
'webStorageEnabled': True,
'webdriver.remote.sessionid': '1cf77f237e966bac6ca15d4d9c107423'},
'command_executor': <selenium.webdriver.remote.remote_connection.RemoteConnection object at 0x7fb42be0cf98>,
'error_handler': <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x7fb427d08a20>,
'session_id': '1cf77f237e966bac6ca15d4d9c107423',
'w3c': False}

为什么我仍然看到ERR_SSL_PROTOCOL_ERROR

此错误消息...

This site can’t provide a secure connection app sent an invalid response. ERR_SSL_PROTOCOL_ERROR

。意味着ChromeDriver无法启动/生成新的WebBrowser,即本地主机上的Chrome浏览器会话。

根据此评论,当您在本地主机(没有HTTPS)上看到此问题时,盲折解决方案是通过chromeOptions()添加argument--allow-insecure-localhost,如下所示:

'goog:chromeOptions': {'args': ['--allow-insecure-localhost'],
'extensions': []}

但是,您的主要问题似乎与您设置platform设置的功能有关,ANY如下:

{'acceptInsecureCerts': True,
'browserName': 'chrome',
'goog:chromeOptions': {'args': ['--ignore-certificate-errors'],
'extensions': []},
'platform': 'ANY',
'version': ''}

根据 WebDriver - W3C Living 文档的平台名称部分提到的,以下平台名称通常具有易于理解的语义,并且在匹配功能时,可以通过将它们作为已知操作系统的有效同义词来实现最大的互操作性:

Key         System
---         ------
"linux"     Any server or desktop system based upon the Linux kernel.
"mac"       Any version of Apple’s macOS.
"windows"   Any version of Microsoft Windows, including desktop and mobile versions.

注意:此列表并非详尽无遗。

从"新建会话"返回功能时,返回更具体的平台名称是有效的,从而允许用户正确识别运行 WebDriver 实现的操作系统。

因此,与其在desiredCapabilities对象中传递"platform":"ANY",不如更具体的"platform":"linux"更理想的方法。

您可以在 Curl 错误中找到相关且相关的讨论 http POST 到/session 与参数: {"desiredCapabilities":{"browserName":"chrome","platform":"ANY" 与 Selenium 和 PHPUnit


有关ChromeDriver,ChromeSelenium Clientvrsion的更多信息将帮助我们以更好的方式分析问题。但是,根据ChromeDriver历史记录,与处理证书错误相关的以下问题在ChromeDriver的最后几个版本中得到解决:

允许通过 DevTools 处理证书错误
  • :由于无外设镶边无法显示 SSL 证书错误的 UI 警告,因此发布了修补程序,以将错误公开为 DevTools 事件,并控制要通过 DevTools 命令执行的操作。
  • 提供在Chromedriver/Selenium中处理无头证书错误的能力:早些时候,通过Chromium的UI版本中的CLI开关控制的某些与安全相关的选项(如--ignore-certificate-errors)被静默忽略,只能通过devtools进行设置。因此,有必要在浏览器目标 DevTools 客户端上重写和处理certificateError事件。发布了一个修复程序,实现了使用新的 DevTools 方法来覆盖浏览器范围内的证书错误处理,这也允许在无头模式下忽略证书错误。
  • 通过 DevTools 处理全局证书错误:以前 DevTools 允许处理单个目标/WebContent 的证书错误,但是当创建新目标时(例如单击目标=_blank链接),在尝试导航之前,通常不可能足够快地发送Security.enable/Security.setOverrideCertificateErrors命令。使用更简单的"忽略所有证书错误"模式发布了修复程序,而是弃用了旧的覆盖命令,转而使用新的setIgnoreCertificateErrors命令,该命令还公开浏览器目标上的安全域,以便于对整个浏览器全局应用此覆盖。

结论

  • 确保添加了以下参数/功能:
    • --allow-insecure-localhost
    • acceptInsecureCerts
    • --ignore-certificate-errors
  • 当您使用时'chromedriverVersion': '74.0.3729.6'请确保您也在使用'chrome': '74.0'(根据 ChromeDriver v74.0.3729.6 发行说明)
  • 确保您使用的是最新发布的Selenium v3.141.59客户端。

根据修复"Aw,Snap!"页面崩溃和其他页面加载错误 - 计算机 - 谷歌浏览器帮助(展开"页面加载错误代码和问题"部分),Chrome 为任何与 SSL 相关的错误提供ERR_SSL_PROTOCOL_ERROR这包括:

  • 证书错误
  • 连接参数协商失败(例如要使用的 TLS 版本和流加密)
  • 对等方违反协议

由于您无法从Chrome获取更多详细信息,因此在其他应用(例如Firefox或openssl s_client)中打开页面可能会为您提供有关正在发生的事情的更多详细信息。

例如,使用Wireshark嗅探数据包可以显示连接的初始阶段,包括协商阶段;如果服务器是你的(所以你有它的私钥),你也可以解密加密的部分 - 这将给你完整的画面。

您正在通过HTTP而不是HTTPS请求页面。 Chrome 无法连接到不安全的HTTP服务器。

这会导致 TLS/SSL 协商失败。

您需要确保您的服务器在 TCP 端口 8000 上运行HTTPS

使用--ignore-certificate-errors选项,您可以生成自签名证书并将其应用于 Web 服务器。

然后将网址行更改为使用HTTPS

app_login_url = 'https://app:8000/accounts/login/'

我在MAC上遇到了这个问题,添加chrome选项并没有解决它。

以下解决方法为我解决了问题:

  • 导航到/usr/local/lib/python/site-packages/seleniumwire/proxy
  • 双击ca.crt文件
  • Keychain Access应用程序中,双击Selenium Wire CA证书
  • 展开Trust
  • 从下拉列表中选择Always Trust选项
  • 使用密码进行身份验证

如果有人在搜索 nodejs 答案时偶然发现这一点,它是类似的......

import * as chromey from 'selenium-webdriver/chrome.js';
const chromeOptions = new chromey.Options();
chromeOptions.addArguments(
'--ignore-certificate-errors',
'--no-sandbox',
// '--headless',
'disable-gpu',
);
const driver = new Builder()
.forBrowser('chrome')
.setChromeOptions(chromeOptions)
.setCapability("acceptInsecureCerts", true)
.build();

最新更新