记一次WebDriver无法正常加载www.xxx.com域名Cookie文件的解决办法

@zxniuniu   2019-05-29  
1 评论   373 浏览

具体问题为,在使用WebDriver正常登录网址后,进行了Cookie保存,但在下次自动反序列化加载Cookie时发现无法正常加载,导致每次需要重新登录验证,目前采用了一种曲线救国的方式,在序列化Cookie时调整域名为xxx.com,具体方案如下。

具体问题大家也可以参见:Add cookie exception when dot exists before domain name

首先,在成功登录后序列化Cookie时:

/**
 * 序列化CookieStore
   * @param driver WebDriver
   * @param cookieFile 序列化地址
   * @return 是否序列化成功
   */
  public static boolean saveCookies(WebDriver driver, String cookieFile){
     try{
        Options options = driver.manage();
        Set<Cookie> cookieSet = options.getCookies();

        CookieStore cookieStore = CookieUtils.driverCookie2HttpCookie(cookieSet);

        return ObjectUtils.serializeFile(cookieStore, cookieFile);
     }catch(Exception e){
        e.printStackTrace();
        return false;
     }
  }
/**
 * 将获取的DriverCookie值转换为HttpCookie
 * @param driver WebDriver
 * @return CookieStore 
 */
public static CookieStore driverCookie2HttpCookie(Set<org.openqa.selenium.Cookie> cookies) {
    CookieStore store = new BasicCookieStore();

    for (org.openqa.selenium.Cookie cookie : cookies) {
        BasicClientCookie bcc = new BasicClientCookie(cookie.getName(), cookie.getValue());
      
        // log.debug("[" + cookie.getName() + "]=[" + cookie.getValue() + "]" + cookie.getDomain() == null ? "" : cookie.getDomain());
      
        // 整理Cookie,将www去掉,否则Driver在addCookies时将会自动在前面加.,即www.abc.com变成.www.abc.com,从而无法使用
	String domain = cookie.getDomain();
        bcc.setDomain(StringUtils.isEmpty(domain) ? null : domain.startWiths("www") ? domain.substring(3) : domain);
      
        bcc.setPath(cookie.getPath().equals("//") ? "/" : cookie.getPath());
        bcc.setExpiryDate(cookie.getExpiry());
      
        store.addCookie(bcc);
    }
    
    return store;
  }

然后就可以在下次加载WebDriver时正常加载Cookie了

/**
 * 给指定的URL填充Cookie
 * @param url 要加载的地址
 */
protected void addCookies(String url) {
    driver.get(url);
        
    if(null != cookieStore){
        driver.addCookies(cookieStore);
        driver.refresh();
        driver.waitPageLoad();
    }
}
/**
 * 给Driver增加Cookie
 * @param driver
 * @return
 */
public void addCookies(CookieStore cookieStore) {
    Options options = driver.manage();
    List<Cookie> cookieList = CookieUtils.httpCookie2DriverCookie(cookieStore);
    for(Cookie cookie : cookieList){
        // 整理Cookie,将www去掉,否则回填时将会自动在前面加.,即www.abc.com,将变成.www.abc.com,而无法使用
        // 一般情况下在序列化时已经解决了前置www的问题,在这儿应该就不需要再验证了,但考虑到部分已经存在的CookieStore还存在前置www的问题,所以可以应用验证
        // cookie = new Cookie(cookie.getName(), cookie.getValue(), 
        //       CookieUtils.modifyDomain4Driver(cookie.getDomain()), cookie.getPath(), cookie.getExpiry(), false, false);
        
        options.addCookie(cookie);
    }
  }

到这儿,可能有人要问了,序列化时干嘛转来转去的,把Set转换为CookieStore,纯粹CookieStore有其它用处,你也可以不转换直接序列化。

另外,注意在WebDriver加载Cookie前需要先打开网址,不能直接先加载Cookie,Cookie要加载到某个域名下,因此,需要先打开网址,再加载Cookie,加载完成后refresh刷新页面,最后通过规则指定是否加载(登录)成功。

参见:https://github.com/SeleniumHQ/selenium/issues/4861


评论列表

  • zxniuniu 回复»

    目前还没找到更优雅的方式来解决这个域名问题,不过经测试,有的网站在更改Cookie域名后也没问题,有的就不行,显示未登录状态。
    另外,还有一个思路,增加Driver池,仅在第一次需要登录,后面直接从池中拿Driver,但貌似进程一多内存耗不起。
    后面有空了再继续Google吧。也欢迎大家讨论。

添加新评论