我们在进行接口自动化工作时,业务接口往往需要权限验证才能调通,所以首先需调用登录接口,登录成功后,拿到该接口返回的 Token,但由于有的 Web 系统不能通过接口获取到 Token,所以只能先手动打开浏览器->输入账号密码->点击登录->打开 F12 拿到 Token,再复制粘贴到调用接口所需要的参数中,若 Token 设置了有效期,则要反复执行次步骤,导致接口自动化也没有很自动,以下介绍此类问题的解决方法。
使用 Selenium 打开系统登录页面,输入账号密码,登录成功后抓包,拿到可以获取 Token 的接口,并将抓到 Token 存到数据库或存到本地文件中。之后请求接口时,先读取 Token,再传递到请求参数中。
BrowserMobProxy 一款基于 Java 的代理服务,类似我们使用的 Fiddler,即开启一个端口并作为一个标准代理存在,当 HTTP 客户端(浏览器等)设置了这个代理,则抓取并有能力修改所有的请求细节并获取返回内容。支持 Java、Python。
初始化 BrowserMobProxy(相当于打开 Fiddler)
BrowserMobProxy browserMobProxy = new BrowserMobProxyServer();
browserMobProxy.start();
browserMobProxy.enableHarCaptureTypes(CaptureType.REQUEST_CONTENT, CaptureType.RESPONSE_CONTENT);
browserMobProxy.setHarCaptureTypes(CaptureType.RESPONSE_CONTENT);
browserMobProxy.newHar("qym");
Proxy seleniumProxy = ClientUtil.createSeleniumProxy(browserMobProxy);
// 设置浏览器参数
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
capabilities.setCapability(CapabilityType.PROXY,seleniumProxy);
ChromeOptions options = new ChromeOptions();
capabilities.setCapability(ChromeOptions.CAPABILITY, options);
capabilities.setCapability(CapabilityType.ACCEPT_SSL_CERTS,true);
capabilities.setCapability(CapabilityType.ACCEPT_INSECURE_CERTS,true);
初始化 WebDriver 并打开浏览器访问 Web 系统
WebDriver driver = new ChromeDriver(capabilities);
//打开链接
driver.get("https://***-***-ccms.***.com/portal/index.html#/***");
driver.manage().window().maximize();
Thread.sleep(500);
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
由于 Selenium 每次打开一个浏览器窗口,都是没有 Cookie 的窗口,相当于 Chrome 的无痕模式,但本 Web 系统使用新浏览器访问时,需要输入手机验证码,对于自动化来说,会比较麻烦,估而采取以下方式,首先打开之前访问过该网站的浏览器,输入 url,打开该网页拿到 Cookie(Chrome:F12->点击 Application->找到左侧 Storage 一栏中 Cookie,拿到所需的数据),使用 Cookie 注入的方式,在每次 Selenium 打开浏览器时,将 Cookie 注入到浏览器中。这样就不需要再输入手机验证码。
Cookie c1 = new Cookie("_ati","***");
Cookie c2 = new Cookie("x_session","***");
Cookie c3 = new Cookie("tenantId","***");
Cookie c4 = new Cookie("sy-cook","***");
Cookie c5 = new Cookie("***.***.com","***");
Cookie c6 = new Cookie("acw_tc","***");
Cookie c7 = new Cookie("SDPID","***.***.Xaf5htP0Jd_B8IZnErSLlc7Emfv3--8hewnhs6irL5U");
Cookie c8 = new Cookie("JSESSIONID","***.***.***--8hewnhs6irL5U");
Cookie c9 = new Cookie("ccmsRequestCredential","***");
Thread.sleep(500);
driver.manage().addCookie(c1);
System.out.println(""+c1);
driver.manage().addCookie(c2);
driver.manage().addCookie(c3);
driver.manage().addCookie(c4);
driver.manage().addCookie(c5);
driver.manage().addCookie(c6);
driver.manage().addCookie(c7);
driver.manage().addCookie(c8);
driver.manage().addCookie(c9);
driver.navigate().refresh();
Thread.sleep(500);
driver.get("https://***-***-ccms.***.com/portal/index.html#/***");
List<WebElement> ButtonElement = driver.findElements(By.className("***-input"));
ButtonElement.get(0).sendKeys("**************");
ButtonElement.get(1).sendKeys("***@***");
driver.findElement(By.id("btn")).click();
Thread.sleep(500);
此时 BrowserMobProxy 已经拿到了以上步骤访问过的接口,存到了 Har,但抓到的接口众多,并不是每个接口都返回了 Token,所以需要先手动筛选能返回 Token 的接口,找到该接口,并拿到该接口返回的 Json,获取到 json 中存在 Token 的 Key、Value,拿到 Token,并写入到本地文件中供后续接口自动化过程使用。
Har har = browserMobProxy.getHar();
List<HarEntry> entries = har.getLog().getEntries();
for (HarEntry harEntry : entries) {
String url = harEntry.getRequest().getUrl();
HarResponse response = harEntry.getResponse();
String conent = response.getContent().getText();
if (url.contains("/***")){
JSONObject jsonObject = JSONObject.parseObject(conent);
System.out.println(jsonObject.get("id"));
TokenFile.witerFile((String) jsonObject.get("id"),"E:\\JavaCode\\AllureTest\\src\\main\\java\\Token.txt");
break;
}
}
关闭浏览器窗口,由于此 Web 系统会弹出新窗口,若只使用 driver.close() 只能关掉当前窗口,不能关闭所有窗口,所以要拿到所有已打开浏览器的窗口,逐个关闭。
Set<String> handles = driver.getWindowHandles();
String CurlHandle =driver.getWindowHandle();
for(String s: handles) {
if (s.equals(CurlHandle)) {
driver.close();
continue;
} else {
driver.switchTo().window(s);
driver.close();
}
}
以下是完整代码
public class GetToken {
public static void main(String[] args) throws InterruptedException {
testProxy();
}
public static void testProxy() throws InterruptedException {
//初始化browserMobProxy
BrowserMobProxy browserMobProxy = new BrowserMobProxyServer();
browserMobProxy.start();
browserMobProxy.enableHarCaptureTypes(CaptureType.REQUEST_CONTENT, CaptureType.RESPONSE_CONTENT);
browserMobProxy.setHarCaptureTypes(CaptureType.RESPONSE_CONTENT);
browserMobProxy.newHar("qym");
Proxy seleniumProxy = ClientUtil.createSeleniumProxy(browserMobProxy);
// 设置浏览器参数
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
capabilities.setCapability(CapabilityType.PROXY,seleniumProxy);
ChromeOptions options = new ChromeOptions();
capabilities.setCapability(ChromeOptions.CAPABILITY, options);
capabilities.setCapability(CapabilityType.ACCEPT_SSL_CERTS,true);
capabilities.setCapability(CapabilityType.ACCEPT_INSECURE_CERTS,true);
// 创建驱动对象
WebDriver driver = new ChromeDriver(capabilities);
//打开链接
driver.get("https://qa-***-***.***.com/portal/index.html#/***");
driver.manage().window().maximize();
Thread.sleep(500);
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
Thread.sleep(500);
Cookie c1 = new Cookie("_ati","***");
Cookie c2 = new Cookie("x_session","***");
Cookie c3 = new Cookie("tenantId","***");
Cookie c4 = new Cookie("sy-cook","***");
Cookie c5 = new Cookie("***.******.com","***");
Cookie c6 = new Cookie("acw_tc","***");
Cookie c7 = new Cookie("SDPID",".***");
Cookie c8 = new Cookie("JSESSIONID","***");
Cookie c9 = new Cookie("ccmsRequestCredential","***");
Thread.sleep(500);
driver.manage().addCookie(c1);
System.out.println(""+c1);
driver.manage().addCookie(c2);
driver.manage().addCookie(c3);
driver.manage().addCookie(c4);
driver.manage().addCookie(c5);
driver.manage().addCookie(c6);
driver.manage().addCookie(c7);
driver.manage().addCookie(c8);
driver.manage().addCookie(c9);
driver.navigate().refresh();
Thread.sleep(500);
driver.get("https://qa-***ccms.****.com/portal/index.html#/customerGrouping");
List<WebElement> ButtonElement = driver.findElements(By.className("cloud-input"));
ButtonElement.get(0).sendKeys("***.****");
ButtonElement.get(1).sendKeys("****@***");
driver.findElement(By.id("btn")).click();
Thread.sleep(500);
List<WebElement> ButtonElement2 = driver.findElements(By.className("***"));
ButtonElement2.get(0).click();
Thread.sleep(1000);
// 获取返回的请求内容
Har har = browserMobProxy.getHar();
List<HarEntry> entries = har.getLog().getEntries();
for (HarEntry harEntry : entries) {
String url = harEntry.getRequest().getUrl();
HarResponse response = harEntry.getResponse();
String conent = response.getContent().getText();
if (url.contains("/web-***/***/***")){
JSONObject jsonObject = JSONObject.parseObject(conent);
System.out.println(jsonObject.get("id"));
TokenFile.witerFile((String) jsonObject.get("id"),"E:\\JavaCode\\AllureTest\\src\\main\\java\\Token.txt");
break;
}
}
Set<String> handles = driver.getWindowHandles();
String CurlHandle =driver.getWindowHandle();
for(String s: handles) {
if (s.equals(CurlHandle)) {
driver.close();
continue;
} else {
driver.switchTo().window(s);
driver.close();
}
}
System.exit(0);
}
}