困惑的CookieHandler [英] Puzzled by CookieHandler

查看:126
本文介绍了困惑的CookieHandler的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要访问一些网页,并通过浏览器的方式传递cookie。这很容易使用

  CookieHandler.setDefault(new MyCookieManager()); 

但这引入了我需要避免的全局状态(假设同时访问同一服务器上的两个帐户) 。所以我想做的是像

  String doGetWithCookies(URL url,MyCookies myCookies){
HttpsURLConnection conn =(HttpsURLConnection)url.openConnection();
myCookies.addToRequest(...);
myCookies.updateFromResponse(...);
return getHttpBody(conn);
}

但我看不出如何做。 CookieManager.get put 的方法接受 URL ,但我想使用 c $ 不同帐户的 URL 的不同Cookie



我试过的:没有什么,因为只有四个方法可用,一个单一的子类,没有任何适合。手动解析标头肯定是可行的,但是在2014年我没有选择。我知道 Apache Http客户端< a>,但是1.我希望琐碎的东西不需要半个兆字节的库,2.第一眼看来我也看不到一个解决方案。



澄清:



想象一下,您想要锁定为SO作为两个不同的用户。您可以在一台计算机上使用两台计算机或两个不同的浏览器(Chrome和Firefox)来实现。您无法在单个浏览器的两个标签页中执行此操作。



我想要的是相当于模拟两个浏览器的可能性。在此期间,我发现了一个相关问题,并张贴了黑客解决方案



仍然我在寻找 CookieHandler 设计背后的解释。

解决方案

这里的根本问题是,你提到的是

  CookieHandler.setDefault(new MyCookieManager ; 

引入全局状态。为什么Oracle不能提供一种基于每个会话来管理Cookie的简单方法。



不过,您可以这样做。


  1. 包含 URLConnectionCookieManager 类,有两种方法: setCookiesFromCookieJar(urlConnection) putCookiesInCookieJar(urlConnection)

  2. 为每个单独的会话创建 URLConnectionCookieManager 类。 (注意,它的方法不是静态的,它们是实例方法。)

  3. 在发送请求之前,调用 urlConnectionCookieManager.setCookiesFromCookieJar(urlConnection)

  4. 发送请求后,调用 urlConnectionCookieManager.putCookiesInCookieJar(urlConnection)
  5. code>。此方法从连接中检索Cookie,并将其放入cookie jar中。

确保使用 URLConnectionCookieManager



URLConnectionCookieManager类如下所示:

 包http; 

import java.net.URLConnection;
import java.net.CookieManager;
import java.net.CookieHandler;
import java.net.CookieStore;
import java.net.CookiePolicy;
import java.net.URL;
import java.net.URI;
import java.util.List;
import java.util.Iterator;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.io.IOException;
import java.io.Serializable;
import java.net.URISyntaxException;


public class URLConnectionCookieManager implements Serializable
{

public URLConnectionCookieManager()
{
this(null,null);
}

public URLConnectionCookieManager(
CookieHandler cookieHandler)
{
setCookieHandler(cookieHandler);
}

public URLConnectionCookieManager(
CookieStore cookieStore,
CookiePolicy cookiePolicy)
{
CookieHandler cookieHandler = createCookieHandler(cookieStore,cookiePolicy);
setCookieHandler(cookieHandler);
}

public void putCookiesInCookieJar(
URLConnection urlConnection)throws IOException
{
Map< String,List< String> headers = urlConnection.getHeaderFields();
URL url = urlConnection.getURL();

URI uri = null;
try
{
uri = url.toURI();
}
catch(URISyntaxException urise)
{
System.out.println(在cookie jar中放置cookie时无法将URL转换为URI。
throw new IOException(urise);
}

CookieHandler cookieHandler = getCookieHandler();
cookieHandler.put(uri,headers);
}

public void setCookiesFromCookieJar(
URLConnection urlConnection)throws IOException
{
Map< String,List< String> headerMap = new HashMap< String,List< String>>();

URL url = urlConnection.getURL();

URI uri = null;
try
{
uri = url.toURI();
}
catch(URISyntaxException urise)
{
System.out.println(在从cookie jar设置cookie时无法将URL转换为URI);
throw new IOException(urise);
}

CookieHandler cookieHandler = getCookieHandler();
headerMap = cookieHandler.get(uri,headerMap);

Set< Map.Entry< String,List< String>>> headerSet = headerMap.entrySet();
Iterator< Map.Entry< String,List< String>>> headerIterator = headerSet.iterator();
boolean hasNextPair = headerIterator.hasNext();
while(hasNextPair)
{
Map.Entry< String,List< String>> pair = headerIterator.next();
String key = pair.getKey();
List< String> cookieList = pair.getValue();

迭代器< String> cookieIterator = cookieList.iterator();
boolean hasNextCookie = cookieIterator.hasNext();
while(hasNextCookie)
{
String cookie = cookieIterator.next();
urlConnection.addRequestProperty(key,cookie);
hasNextCookie = cookieIterator.hasNext();
}

hasNextPair = headerIterator.hasNext();
}
}

public CookieHandler getCookieHandler()
{
return this.cookieHandler_;
}

protected CookieHandler createCookieHandler(
CookieStore cookieStore,
CookiePolicy cookiePolicy)
{
CookieHandler cookieHandler = new CookieManager(cookieStore,cookiePolicy) ;

return cookieHandler;
}

protected void setCookieHandler(
CookieHandler cookieHandler)
{
this.cookieHandler_ = cookieHandler;
}

private CookieHandler cookieHandler_;

}


I need to access some web pages and pass cookies around the way browsers do. This is easily done using

CookieHandler.setDefault(new MyCookieManager());

but this introduces global state which I need to avoid (Imagine accessing two accounts on the same server concurrently). So what I'd like to do is something like

String doGetWithCookies(URL url, MyCookies myCookies) {
    HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
    myCookies.addToRequest(...);
    myCookies.updateFromResponse(...);
    return getHttpBody(conn);
}

but I can't see how to do it. The methods CookieManager.get and put do accept an URL, but I want to use

  • the same cookies with different URLs
  • different cookies for the same URL for different accounts

What I've tried: Nothing as there are just four methods available and a single subclass and nothing fits. Parsing the headers manually is surely doable but IMHO no option in 2014. I know about the Apache Http Client, but 1. I'd hope something that trivial needs no half a megabyte library, 2. at the first glance I can't see a solution there either.

Clarification:

Imagine you want to lock to SO as two different users. You can do it by using two computers or two different browsers (Chrome and Firefox) on a single computer. You can't do it in two tabs of a single browser.

What I want is equivalent to the possibility of simulating two browser. In the meantime I've found a related question and posted hacky solution to it.

Still I'm looking for an explanation behind the CookieHandler design.

解决方案

The fundamental problem here, as you mentioned is that

CookieHandler.setDefault(new MyCookieManager());

introduces a global state. Why Oracle failed to provide a simple means of managing cookies on a per session basis is beyond me.

Here's how you can do it, though.

  1. Include a URLConnectionCookieManager class with two methods: setCookiesFromCookieJar(urlConnection) and putCookiesInCookieJar(urlConnection).
  2. For each separate session, create an instance of the URLConnectionCookieManager class. (Note that its methods are NOT static; they are instance methods.)
  3. Before sending a request, call urlConnectionCookieManager.setCookiesFromCookieJar(urlConnection). This method retrieves cookies from the "cookie jar" and adds them to the connection's request headers.
  4. After sending a request, call urlConnectionCookieManager.putCookiesInCookieJar(urlConnection). This method retrieves cookies from the connection and puts them in the "cookie jar".

Make sure you use the instance of URLConnectionCookieManager that corresponds to the "session".

The URLConnectionCookieManager class looks like this:

package http;

import java.net.URLConnection;
import java.net.CookieManager;
import java.net.CookieHandler;
import java.net.CookieStore;
import java.net.CookiePolicy;
import java.net.URL;
import java.net.URI;
import java.util.List;
import java.util.Iterator;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.io.IOException;
import java.io.Serializable;
import java.net.URISyntaxException;


public class URLConnectionCookieManager implements Serializable
  {

  public URLConnectionCookieManager()
    {
    this(null, null);
    }

  public URLConnectionCookieManager(
    CookieHandler cookieHandler)
    {
    setCookieHandler(cookieHandler);
    }

  public URLConnectionCookieManager(
    CookieStore cookieStore,
    CookiePolicy cookiePolicy)
    {
    CookieHandler cookieHandler = createCookieHandler(cookieStore, cookiePolicy);
    setCookieHandler(cookieHandler);
    }

  public void putCookiesInCookieJar(
    URLConnection urlConnection) throws IOException
    {
    Map<String, List<String>> headers = urlConnection.getHeaderFields();
    URL url = urlConnection.getURL();

    URI uri = null;
    try
      {
      uri = url.toURI();
      }
    catch (URISyntaxException urise)
      {
      System.out.println("Unable to convert URL to URI while putting cookies in cookie jar.");
      throw new IOException(urise);
      }

    CookieHandler cookieHandler = getCookieHandler();
    cookieHandler.put(uri, headers);
    }

  public void setCookiesFromCookieJar(
    URLConnection urlConnection) throws IOException
    {
    Map<String, List<String>> headerMap = new HashMap<String, List<String>>();

    URL url = urlConnection.getURL();

    URI uri = null;
    try
      {
      uri = url.toURI();
      }
    catch (URISyntaxException urise)
      {
      System.out.println("Unable to convert URL to URI while setting cookies from cookie jar.");
      throw new IOException(urise);
      }

    CookieHandler cookieHandler = getCookieHandler();
    headerMap = cookieHandler.get(uri, headerMap);

    Set<Map.Entry<String, List<String>>> headerSet = headerMap.entrySet();
    Iterator<Map.Entry<String, List<String>>> headerIterator = headerSet.iterator();
    boolean hasNextPair = headerIterator.hasNext();
    while (hasNextPair)
      {
      Map.Entry<String, List<String>> pair = headerIterator.next();
      String key = pair.getKey();
      List<String> cookieList = pair.getValue();

      Iterator<String> cookieIterator = cookieList.iterator();
      boolean hasNextCookie = cookieIterator.hasNext();
      while (hasNextCookie)
        {
        String cookie = cookieIterator.next();
        urlConnection.addRequestProperty(key, cookie);
        hasNextCookie = cookieIterator.hasNext();
        }

      hasNextPair = headerIterator.hasNext();
      }
    }

  public CookieHandler getCookieHandler()
    {
    return this.cookieHandler_;
    }

  protected CookieHandler createCookieHandler(
    CookieStore cookieStore,
    CookiePolicy cookiePolicy)
    {
    CookieHandler cookieHandler = new CookieManager(cookieStore, cookiePolicy);

    return cookieHandler;
    }

  protected void setCookieHandler(
    CookieHandler cookieHandler)
    {
    this.cookieHandler_ = cookieHandler;
    }

  private CookieHandler cookieHandler_;

  }

这篇关于困惑的CookieHandler的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆