如何在Selenium+Chrome WebDriver中禁用错误密码时的认证弹窗?
解决Chrome非无头模式下禁用HTTP认证弹窗,获取401页面的方案
我之前也遇到过这个问题——Chrome自带的认证弹窗确实会打断Selenium的测试流程,没办法直接获取服务器返回的401页面。这里有两种可靠的解决方法,都能在非无头模式下禁用弹窗,让你顺利验证密码错误返回401、密码正确返回200的测试场景:
方法一:URL嵌入认证信息(简单直接)
HTTP基本认证支持在URL中直接嵌入用户名和密码,格式为http://username:password@target-domain.com。Chrome会自动将这些凭证添加到请求头的Authorization字段中,不会弹出认证弹窗;如果密码错误,服务器会直接返回401页面,而非重试弹窗。
注意事项
Chrome 81及以上版本默认会拦截这种带凭证的URL,所以需要添加启动参数解除限制:
// 配置ChromeOptions,允许URL中的凭证认证 ChromeOptions options = new ChromeOptions(); options.addArguments("--allow-url-auth-bypass-for-testing"); // 如果目标是HTTPS且使用自签证书,需添加以下参数避免拦截 options.addArguments("--ignore-certificate-errors"); WebDriver webDriver = new ChromeDriver(options);
修改导航代码
将用户名和密码拼接进目标URL:
String username = System.getProperty("id"); String password = System.getProperty("password"); String urlToOpen = "https://your-target-url.com"; // 替换为你的目标URL // 拆分URL的协议和域名部分,拼接凭证 String[] urlParts = urlToOpen.split("://"); String authenticatedUrl = String.format("%s://%s:%s@%s", urlParts[0], username, password, urlParts[1]); webDriver.navigate().to(authenticatedUrl);
方法二:使用Chrome DevTools Protocol(CDP)设置请求头(更可靠)
如果URL嵌入凭证的方式被浏览器安全策略限制,推荐使用CDP直接在请求头中添加Authorization字段。这种方法不需要修改URL,兼容性更好。
代码示例
ChromeOptions options = new ChromeOptions(); WebDriver webDriver = new ChromeDriver(options); // 初始化CDP会话 DevTools devTools = ((ChromeDriver) webDriver).getDevTools(); devTools.createSession(); devTools.send(Network.enable(Optional.empty(), Optional.empty(), Optional.empty())); // 生成Base64编码的认证信息 String username = System.getProperty("id"); String password = System.getProperty("password"); String authCredentials = username + ":" + password; String encodedAuth = Base64.getEncoder().encodeToString(authCredentials.getBytes(StandardCharsets.UTF_8)); String authHeader = "Basic " + encodedAuth; // 设置全局请求头,添加Authorization字段 devTools.send(Network.setExtraHTTPHeaders(new Headers(Map.of("Authorization", authHeader)))); // 导航到目标URL webDriver.navigate().to(urlToOpen);
验证状态码和页面内容
Selenium本身没有直接获取HTTP状态码的API,需要通过CDP监听网络请求来获取:
// 监听请求完成事件,收集目标URL的状态码 List<Integer> statusCodes = new ArrayList<>(); devTools.addListener(Network.responseReceived(), response -> { if (response.getResponse().getUrl().equals(urlToOpen)) { statusCodes.add(response.getResponse().getStatus()); } }); // 等待请求完成后验证 Integer statusCode = statusCodes.get(0); if (password.equals("wrongpass")) { // 验证密码错误场景 assert statusCode == 401 : "密码错误时应返回401"; assert webDriver.getPageSource().contains("401 Unauthorized") : "页面应包含401提示"; } else { // 验证密码正确场景 assert statusCode == 200 : "密码正确时应返回200"; }
额外注意事项
- 确保Chrome WebDriver版本与Chrome浏览器版本完全匹配,否则CDP功能可能失效。
- 非无头模式下,以上两种方法均有效,不会触发浏览器的认证弹窗。
- 如果测试环境使用HTTPS,需根据实际情况添加证书相关的启动参数。
内容的提问来源于stack exchange,提问作者Stéphane GRILLON




