将 ssl 证书添加到 selenium-webdriver
Add ssl certificate to selenium-webdriver
我使用 selenium 对 chromeDriver 进行端到端测试。要测试的网站需要 ssl 证书。当我手动打开浏览器时,有一个弹出窗口让我 select 一个已安装的证书。不同的测试访问不同的URL,也需要不同的证书。但是,如果我 运行 在无头模式下进行测试,则没有弹出窗口。所以我需要一种方法来以编程方式设置证书(例如设置 .pem
文件)以用于当前测试。
我怎样才能做到这一点?
我尝试设置一个 browserMob 代理,然后将其配置为 selenium 中的代理 - 但是,这似乎没有任何作用......有更好的方法吗?我究竟做错了什么?这是我尝试过的:
PemFileCertificateSource pemFileCertificateSource = new PemFileCertificateSource(
new File("myCertificate.pem"),
new File("myPrivateKey.pem"),
"myPrivateKeyPassword");
ImpersonatingMitmManager mitmManager = ImpersonatingMitmManager.builder()
.rootCertificateSource(pemFileCertificateSource)
.build();
BrowserMobProxy browserMobProxy = new BrowserMobProxyServer();
browserMobProxy.setTrustAllServers(true);
browserMobProxy.setMitmManager(mitmManager);
browserMobProxy.start(8080);
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setProxy(ClientUtil.createSeleniumProxy(browserMobProxy));
WebDriver webDriver = new ChromeDriver(chromeOptions);
// use the webdriver for tests, e.g. assertEquals("foo", webDriver.findElement(...))
显然,开箱即用的 BrowserMob 无法做到这一点。因此,我编写了一个代理扩展 SeleniumSslProxy
,它可以插入 Selenium 并添加基于证书的身份验证以创建 HTTPS 连接。
这是它的工作原理:
- 使用 BrowserMob 拦截 Selenium HTTP 请求
- 设置
SSLContext
给定证书(.pfx 文件)和密码
- 使用okhttp将请求转发给目标URL
- 将 okhttp
Response
转换为 netty FullHttpResponse
以便 Selenium 可以处理它
您可以在 github 上找到代码。这是一个如何在 Selenium end-to-end 测试中使用它的示例(也适用于无头模式):
@Before
public void setup() {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
File clientSslCertificate = new File(
classLoader.getResource("certificates/some-certificate.pfx").getFile());
String certificatePassword = "superSecret";
this.proxy = new SeleniumSslProxy(clientSslCertificate, certificatePassword);
this.proxy.start();
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setProxy(proxy);
this.webDriver = new ChromeDriver(chromeOptions);
}
@Test
public void pageTitleIsFoo() {
// given
String url = "http://myurl.lol";
// NOTE: do not use https in the URL here. It will be converted to https by the proxy.
// when
this.webDriver.get(url);
this.webDriver.manage().timeouts().implicitlyWait(5, SECONDS);
// then
WebElement title = this.webDriver.findElement(By.className("title"));
assertEquals("Foo", title.getText());
}
@After
public void teardown() {
this.webDriver.quit();
this.proxy.stop();
}
请注意,我只使用了 chromeDriver,从未用其他驱动程序测试过。可能需要对 SeleniumSslProxy
进行细微调整才能与其他驱动程序一起使用。
我使用 selenium 对 chromeDriver 进行端到端测试。要测试的网站需要 ssl 证书。当我手动打开浏览器时,有一个弹出窗口让我 select 一个已安装的证书。不同的测试访问不同的URL,也需要不同的证书。但是,如果我 运行 在无头模式下进行测试,则没有弹出窗口。所以我需要一种方法来以编程方式设置证书(例如设置 .pem
文件)以用于当前测试。
我怎样才能做到这一点? 我尝试设置一个 browserMob 代理,然后将其配置为 selenium 中的代理 - 但是,这似乎没有任何作用......有更好的方法吗?我究竟做错了什么?这是我尝试过的:
PemFileCertificateSource pemFileCertificateSource = new PemFileCertificateSource(
new File("myCertificate.pem"),
new File("myPrivateKey.pem"),
"myPrivateKeyPassword");
ImpersonatingMitmManager mitmManager = ImpersonatingMitmManager.builder()
.rootCertificateSource(pemFileCertificateSource)
.build();
BrowserMobProxy browserMobProxy = new BrowserMobProxyServer();
browserMobProxy.setTrustAllServers(true);
browserMobProxy.setMitmManager(mitmManager);
browserMobProxy.start(8080);
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setProxy(ClientUtil.createSeleniumProxy(browserMobProxy));
WebDriver webDriver = new ChromeDriver(chromeOptions);
// use the webdriver for tests, e.g. assertEquals("foo", webDriver.findElement(...))
显然,开箱即用的 BrowserMob 无法做到这一点。因此,我编写了一个代理扩展 SeleniumSslProxy
,它可以插入 Selenium 并添加基于证书的身份验证以创建 HTTPS 连接。
这是它的工作原理:
- 使用 BrowserMob 拦截 Selenium HTTP 请求
- 设置
SSLContext
给定证书(.pfx 文件)和密码 - 使用okhttp将请求转发给目标URL
- 将 okhttp
Response
转换为 nettyFullHttpResponse
以便 Selenium 可以处理它
您可以在 github 上找到代码。这是一个如何在 Selenium end-to-end 测试中使用它的示例(也适用于无头模式):
@Before
public void setup() {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
File clientSslCertificate = new File(
classLoader.getResource("certificates/some-certificate.pfx").getFile());
String certificatePassword = "superSecret";
this.proxy = new SeleniumSslProxy(clientSslCertificate, certificatePassword);
this.proxy.start();
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setProxy(proxy);
this.webDriver = new ChromeDriver(chromeOptions);
}
@Test
public void pageTitleIsFoo() {
// given
String url = "http://myurl.lol";
// NOTE: do not use https in the URL here. It will be converted to https by the proxy.
// when
this.webDriver.get(url);
this.webDriver.manage().timeouts().implicitlyWait(5, SECONDS);
// then
WebElement title = this.webDriver.findElement(By.className("title"));
assertEquals("Foo", title.getText());
}
@After
public void teardown() {
this.webDriver.quit();
this.proxy.stop();
}
请注意,我只使用了 chromeDriver,从未用其他驱动程序测试过。可能需要对 SeleniumSslProxy
进行细微调整才能与其他驱动程序一起使用。