为什么选项“--explicitly-allowed-ports”在使用 chrome 版本 91.x 和 selenium/chromedriver 无头模式时不起作用?
Why is option "--explicitly-allowed-ports" not working when using chrome version 91.x and selenium/chromedriver headless mode?
我们有很多由 Jenkins 作业触发的基于 selenium 的测试自动化。测试自动化使用 chromedriver 和无头模式。前几天Jenkins节点安装chrome更新到Version91.x,测试用例全部切换到error状态
我们了解到 Chrome 现在将多个端口视为不安全端口,例如我们用于被测系统的端口 10080。一项小小的研究表明,有一个名为“--explicitly-allowed-ports=10080”的 Chrome 选项应该可以解决这个问题。
对于我们来说,它似乎在 运行 selenium test cases with a browser window 时有效,但在无头模式下 运行 时无效。这是一个已知的问题?有人对此有解释或解决方法吗?
这里是重现问题的简化测试用例:
package com.unsafe.ports;
import java.io.File;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
public class UnsafePortsTest {
@Test
public void testUnsafePorts() {
String url = "http://__SERVER__:10080/__APP__/";
WebDriver driver = createChromeDriver(true);
driver.get(url);
System.out.println("Now at page: " + driver.getTitle());
System.out.println("Page source: " + driver.getPageSource());
}
protected WebDriver createChromeDriver(final boolean headless) {
File driverFile = new File("bin", "chromedriver.exe");
System.setProperty("webdriver.chrome.driver", driverFile.getAbsolutePath());
File chromeExePath = new File("C:/Program Files (x86)/Google/Chrome/Application/chrome.exe");
ChromeOptions chromeOptions = new ChromeOptions();
if (chromeExePath.exists()) {
chromeOptions.setBinary(chromeExePath);
}
if (headless) {
chromeOptions.addArguments("headless");
}
chromeOptions.addArguments("start-maximized");
chromeOptions.addArguments("disable-infobars");
chromeOptions.addArguments("--disable-extensions");
chromeOptions.addArguments("--disable-gpu");
chromeOptions.addArguments("--disable-gpu-sandbox");
chromeOptions.addArguments("--ignore-certificate-errors");
chromeOptions.addArguments("--disable-gpu-compositing");
chromeOptions.addArguments("--no-sandbox-and-elevated");
chromeOptions.addArguments("--disable-web-security");
chromeOptions.addArguments("--hide-scrollbars");
chromeOptions.addArguments("--enable-automation");
chromeOptions.addArguments("--disable-dev-shm-usage");
chromeOptions.addArguments("--explicitly-allowed-ports=10080");
return new ChromeDriver(chromeOptions);
}
}
这是pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com</groupId>
<artifactId>unsafe-ports</artifactId>
<name>unsafe-ports</name>
<description>unsafe-ports</description>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-chrome-driver</artifactId>
<version>3.141.59</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-support</artifactId>
<version>3.141.59</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
下面是我们使用的一些更具体的版本:
- Chrome: 91.0.4472.106
- Chromedriver: 91.0.4472.101
- OS: Windows 服务器 2012 R2
- Java: 1.8.0_73-b02
此致,
塞巴斯蒂安
我希望 Chrome 90 是临时的。所以我在本地实现了上面的示例,但用 Chromium 93 替换了 Chrome 90。使用 headless=false 一切正常 - 使用 headless=是的,它不起作用。
与此同时,我实施了一个类似的测试,但使用 Playwright(在后台也使用 Chromium):headless=true 和 headless=false 都有效,甚至没有提及 --explicitly-allowed-ports.
在没有 --explicitly-allowed-ports 的情况下直接使用 Chromium 会给出错误:ERR_UNSAFE_PORT.
我的结论:Chrome/Chromium 正确处理不安全端口(无头或无头)。所以可能 ChromeDriver 没有给 Chrome.
正确的信息
一个解决方法是安装旧版本的 Chromium 和 Chromedriver(Chromium 不实现自动更新 - 所以你留在选择的版本)。从 2021 年 1 月底开始的页面 https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/ provides builds for Chromium and ChromeDriver. I have chosen build https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/848870/。版本 90.0.4404.0 (Entwickler-Build)(64 位)。
我更改了引用相应 Chromium 和 Chromedriver: headless=true 和 headless=false 的测试项目。测试要求 pagetitle 和页面内容,结果是:
Now at page: Ralfi
Page source: <html><head><title>Ralfi</title></head><body><h1 id="ralf">Hello World!</h1></body></html>
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 3.148 sec
仅供参考:testweb是一个小nodejs。
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('<html><head><title>Ralfi</title></head><body><h1 id="ralf">Hello World!</h1></body></html>');
}).listen(10080);
顺便说一句:我将您的 Chrome 选项减少为仅包含 --explicitly-allowed-ports=10080
我们有很多由 Jenkins 作业触发的基于 selenium 的测试自动化。测试自动化使用 chromedriver 和无头模式。前几天Jenkins节点安装chrome更新到Version91.x,测试用例全部切换到error状态
我们了解到 Chrome 现在将多个端口视为不安全端口,例如我们用于被测系统的端口 10080。一项小小的研究表明,有一个名为“--explicitly-allowed-ports=10080”的 Chrome 选项应该可以解决这个问题。
对于我们来说,它似乎在 运行 selenium test cases with a browser window 时有效,但在无头模式下 运行 时无效。这是一个已知的问题?有人对此有解释或解决方法吗?
这里是重现问题的简化测试用例:
package com.unsafe.ports;
import java.io.File;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
public class UnsafePortsTest {
@Test
public void testUnsafePorts() {
String url = "http://__SERVER__:10080/__APP__/";
WebDriver driver = createChromeDriver(true);
driver.get(url);
System.out.println("Now at page: " + driver.getTitle());
System.out.println("Page source: " + driver.getPageSource());
}
protected WebDriver createChromeDriver(final boolean headless) {
File driverFile = new File("bin", "chromedriver.exe");
System.setProperty("webdriver.chrome.driver", driverFile.getAbsolutePath());
File chromeExePath = new File("C:/Program Files (x86)/Google/Chrome/Application/chrome.exe");
ChromeOptions chromeOptions = new ChromeOptions();
if (chromeExePath.exists()) {
chromeOptions.setBinary(chromeExePath);
}
if (headless) {
chromeOptions.addArguments("headless");
}
chromeOptions.addArguments("start-maximized");
chromeOptions.addArguments("disable-infobars");
chromeOptions.addArguments("--disable-extensions");
chromeOptions.addArguments("--disable-gpu");
chromeOptions.addArguments("--disable-gpu-sandbox");
chromeOptions.addArguments("--ignore-certificate-errors");
chromeOptions.addArguments("--disable-gpu-compositing");
chromeOptions.addArguments("--no-sandbox-and-elevated");
chromeOptions.addArguments("--disable-web-security");
chromeOptions.addArguments("--hide-scrollbars");
chromeOptions.addArguments("--enable-automation");
chromeOptions.addArguments("--disable-dev-shm-usage");
chromeOptions.addArguments("--explicitly-allowed-ports=10080");
return new ChromeDriver(chromeOptions);
}
}
这是pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com</groupId>
<artifactId>unsafe-ports</artifactId>
<name>unsafe-ports</name>
<description>unsafe-ports</description>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-chrome-driver</artifactId>
<version>3.141.59</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-support</artifactId>
<version>3.141.59</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
下面是我们使用的一些更具体的版本:
- Chrome: 91.0.4472.106
- Chromedriver: 91.0.4472.101
- OS: Windows 服务器 2012 R2
- Java: 1.8.0_73-b02
此致, 塞巴斯蒂安
我希望 Chrome 90 是临时的。所以我在本地实现了上面的示例,但用 Chromium 93 替换了 Chrome 90。使用 headless=false 一切正常 - 使用 headless=是的,它不起作用。
与此同时,我实施了一个类似的测试,但使用 Playwright(在后台也使用 Chromium):headless=true 和 headless=false 都有效,甚至没有提及 --explicitly-allowed-ports.
在没有 --explicitly-allowed-ports 的情况下直接使用 Chromium 会给出错误:ERR_UNSAFE_PORT.
我的结论:Chrome/Chromium 正确处理不安全端口(无头或无头)。所以可能 ChromeDriver 没有给 Chrome.
正确的信息一个解决方法是安装旧版本的 Chromium 和 Chromedriver(Chromium 不实现自动更新 - 所以你留在选择的版本)。从 2021 年 1 月底开始的页面 https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/ provides builds for Chromium and ChromeDriver. I have chosen build https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/848870/。版本 90.0.4404.0 (Entwickler-Build)(64 位)。 我更改了引用相应 Chromium 和 Chromedriver: headless=true 和 headless=false 的测试项目。测试要求 pagetitle 和页面内容,结果是:
Now at page: Ralfi
Page source: <html><head><title>Ralfi</title></head><body><h1 id="ralf">Hello World!</h1></body></html>
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 3.148 sec
仅供参考:testweb是一个小nodejs。
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('<html><head><title>Ralfi</title></head><body><h1 id="ralf">Hello World!</h1></body></html>');
}).listen(10080);
顺便说一句:我将您的 Chrome 选项减少为仅包含 --explicitly-allowed-ports=10080