0%

Selenium | 自动登录脚本如何绕过二维码、校验码等安全校验

做 Web UI 自动化测试的朋友,基本上都会遇到用户登录操作,然而基于安全性考虑,登录过程除了要求输入用户名和密码,往往还会存在为了防止自动化登陆而设置的更加复杂的校验。比如,
imag

既然这些校验的存在就是为了对抗 robot、防止自动化登陆,那么,它们自然就成了自动化登陆所面临的难题了。如果知道了这一点,你仍去试着用 Selenium 或其他技术进行破解,那么,在这样做之前,建议你先掂量掂量自己的技术实力吧。

我们自己项目中的安全校验

如果这种校验出现在我们自己的测试项目中,正如我在视频《Web UI 自动化测试:Selenium 入门》中所说,建议你和研发人员沟通,在 test 版本上去除它们,只保留用户和密码即可

解决问题的方法有很多,换一种思路,一切豁然开朗。把“登录过程中二维码/短信验证”从自动化测试用例集中移出,放到手工测试用例集,技术难题就这么轻松愉快的解决了,码农再也不用为了苦思冥想、挠头掉发担心了。

各位看客,山不过来我就过去~~

第三方网站中的安全校验

可是……如果你是在对第三方网站编写网页爬虫,或者编写一些自动化脚本,遇到防自动化登录校验,又该怎么办呢?现在可没有网站程序员帮你临时去掉这个功能模块了。

这种情况,正是本文需要讲解的内容。

半自动化方案

我的解决方案是这样的:

  1. 人工登录所需网站。
  2. 提取页面请求头中的 Cookie。
  3. 将 Cookie 添加到 WebDriver。

前两步很简单,应该是从业人员的基本功,不过多赘述,但下文也会演示。重点在第 3 步,我不确定 Selenium 是否提供了这样的 API,幸运的是,最终在官方 docs 中找到所需的方法。

也许你已经发现了,经过这个方案的处理,我们的自动化变得不纯粹了,它变成了半自动化,因为获取请求 Cookie 的过程是人工的。Anyway,我的自动化脚本至少又可以运行起来了,加入一点点人工介入也是值得的。

另外一点不方便的是,Cookie 中的登录信息都是有有效期的,无论这个网站登录时效使用的是 Cookie 还是 Session,我们不可避免的都需要每隔一段时间重新手工登录网站,获取最新的 Cookie,并在我们的代码中进行替换。

演示

下面我们以头条公众号后台为例演示整个过程。

1、人工登录所需网站

这一步就不演示了,可别泄露了我的密码。
imag

操作步骤:

  1. 点击F12,打开“开发者工具”
  2. 刷新页面,捕获请求
  3. 在左侧请求列表中切换几次,找到Request HeadersCookie有值的请求
  4. Cookie 字段后面的一长串字符串,就是我们需要的
    imag

上一步中得到的 Cookie 字符串还需要经过处理,因为它是很多 Cookie 以分号为分隔符拼接之后的内容,我们需要逆向操作:

  1. 先以“分号;”为分隔符获取 Cookie 列表,
  2. 列表中的元素都含有=号,=左侧是 Cookie 的 name,=右侧是 Cookie 的 value,用 name 和 value 构造 Cookie,
  3. 最后传给 WebDriver。

为了验证我们分析的 “Cookie 字符串是以分号分隔、Cookie 的 name 和 value 在=两侧”,我们仍回到“开发者工具”,切换到 Cookies 卡片下,查看 Cookie 列表完整信息:

imag

编码

闲话少叙,我们开始编码吧。

先解析我们得到的原始 Cookie 字符串,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import org.openqa.selenium.Cookie;

/**
* 将cookie字符串拆解到list中
* @param rawCookie 原始Cookie字符串
* @return Cookie列表
*/
public List<Cookie> parseRawCookie(String rawCookie) {
List<Cookie> cookies = new ArrayList<>();

String[] rawCookieParams = rawCookie.split(";");

for (String cookieParam : rawCookieParams) {
String[] rawCookieNameAndValue = cookieParam.split("=");
if (2 != rawCookieNameAndValue.length) {
log.error("Invalid cookie: missing name and value.");
continue;
}
String cookieName = rawCookieNameAndValue[0].trim();
String cookieValue = rawCookieNameAndValue[1].trim();
Cookie cookie = new Cookie(cookieName, cookieValue);
cookies.add(cookie);
}
return cookies;
}

将上一步得到的 Cookie 列表添加给 WebDriver,这一步需要放在所有需要权限验证的步骤之前。
我们可以先添加 Cookie,然后刷新页面,这样我们打开的网页就是登陆状态了。
imag

编码演示到这里就够用了,大家不妨试试。

API 补充说明

在这个解决方案中,我们主要用到了两个接口,它们还有一些相关接口,如有需要,请自行查阅。

void addCookie(Cookie cookie) // Add a specific cookie.

  • 所属接口:
    org.openqa.selenium.WebDriver.Options
  • 相关方法:
    java.util.Set<Cookie> getCookies()deleteCookie(Cookie cookie) 等等。

Cookie(java.lang.String name, java.lang.String value)

  • 所属接口:
    org.openqa.selenium.Cookie
  • 相关方法:
    Cookie(java.lang.String name, java.lang.String value, java.lang.String domain, java.lang.String path, java.util.Date expiry, boolean isSecure, boolean isHttpOnly) 等等

官方 docs 地址,如下:
https://seleniumhq.github.io/selenium/docs/api/java/

欢迎关注我的其它发布渠道