gpt4 book ai didi

java - 用于多线程的 CookieManager

转载 作者:搜寻专家 更新时间:2023-10-31 08:10:01 34 4
gpt4 key购买 nike

我正在尝试通过线程建立多个连接。

但是每个连接似乎都会覆盖对方的 cookie,导致连接使用错误的 cookie。

在线程类的构造函数中:

    manager = new CookieManager();
manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(manager);

有什么方法可以管理每个线程或每个类的 cookie?

新的失败尝试:

现在每个线程都在使用自己的索引,但它们似乎仍然在 cookie 方面相互覆盖。有什么想法吗?

public class threadedCookieStore implements CookieStore, Runnable {
CookieStore[] store = new CookieStore[1000];
int index;

public threadedCookieStore(int new_index) {
index = new_index;
// get the default in memory cookie store
store[index] = new CookieManager().getCookieStore();


// todo: read in cookies from persistant storage
// and add them store

// add a shutdown hook to write out the in memory cookies
Runtime.getRuntime().addShutdownHook(new Thread(this));
}

public void run() {
// todo: write cookies in store to persistent storage
}

public void add(URI uri, HttpCookie cookie) {
store[index].add(uri, cookie);
}

public List<HttpCookie> get(URI uri) {
return store[index].get(uri);
}

public List<HttpCookie> getCookies() {
return store[index].getCookies();
}

public List<URI> getURIs() {
return store[index].getURIs();
}

public boolean remove(URI uri, HttpCookie cookie) {
return store[index].remove(uri, cookie);
}

public boolean removeAll() {
return store[index].removeAll();
}
}

类内:

threadedCookieStore cookiestore = new threadedCookieStore(index);

manager = new CookieManager(cookiestore,CookiePolicy.ACCEPT_ALL);
manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(manager);

最佳答案

谢谢大家

我对所有答案都投了赞成票,但没有一个有完整的解决方案。

由于通过 google 搜索这个问题可以找到此页面,因此我将发布完整的解决方案并接受我自己的答案:

方法:

1 将CookieHandler扩展为SessionCookieManager

这是基于 How to use different cookies for each connection using HttpURLConnection and the CookieManager in Java , nivs 正确地描述了它,但没有提供完整的解决方案。所以大部分/所有功劳归功于他,我只是在制作完整的 HowTo。 SessionCookieManager 基于 Java 的源代码 http://docs.oracle.com/javase/7/docs/api/java/net/CookieManager.html

import java.io.IOException;
import java.net.CookieHandler;
import java.net.CookiePolicy;
import java.net.CookieStore;
import java.net.HttpCookie;
import java.net.URI;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

public class SessionCookieManager extends CookieHandler
{
private CookiePolicy policyCallback;


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

private final static SessionCookieManager ms_instance = new SessionCookieManager();

public static SessionCookieManager getInstance()
{
return ms_instance;
}

private final static ThreadLocal<CookieStore> ms_cookieJars = new ThreadLocal<CookieStore>() {
@Override
protected synchronized CookieStore initialValue() { return new InMemoryCookieStore(); }
};

public void clear()
{
getCookieStore().removeAll();
}
public SessionCookieManager(CookieStore store,
CookiePolicy cookiePolicy)
{
// use default cookie policy if not specify one
policyCallback = (cookiePolicy == null) ? CookiePolicy.ACCEPT_ALL //note that I changed it to ACCEPT_ALL
: cookiePolicy;

// if not specify CookieStore to use, use default one

}
public void setCookiePolicy(CookiePolicy cookiePolicy) {
if (cookiePolicy != null) policyCallback = cookiePolicy;
}

public CookieStore getCookieStore() {
return ms_cookieJars.get();
}

public Map<String, List<String>>
get(URI uri, Map<String, List<String>> requestHeaders)
throws IOException
{
// pre-condition check
if (uri == null || requestHeaders == null) {
throw new IllegalArgumentException("Argument is null");
}

Map<String, List<String>> cookieMap =
new java.util.HashMap<String, List<String>>();
// if there's no default CookieStore, no way for us to get any cookie
if (getCookieStore() == null)
return Collections.unmodifiableMap(cookieMap);

List<HttpCookie> cookies = new java.util.ArrayList<HttpCookie>();
for (HttpCookie cookie : getCookieStore().get(uri)) {
// apply path-matches rule (RFC 2965 sec. 3.3.4)
if (pathMatches(uri.getPath(), cookie.getPath())) {
cookies.add(cookie);
}
}

// apply sort rule (RFC 2965 sec. 3.3.4)
List<String> cookieHeader = sortByPath(cookies);

cookieMap.put("Cookie", cookieHeader);
return Collections.unmodifiableMap(cookieMap);
}


public void
put(URI uri, Map<String, List<String>> responseHeaders)
throws IOException
{
// pre-condition check
if (uri == null || responseHeaders == null) {
throw new IllegalArgumentException("Argument is null");
}


// if there's no default CookieStore, no need to remember any cookie
if (getCookieStore() == null)
return;

for (String headerKey : responseHeaders.keySet()) {
// RFC 2965 3.2.2, key must be 'Set-Cookie2'
// we also accept 'Set-Cookie' here for backward compatibility
if (headerKey == null
|| !(headerKey.equalsIgnoreCase("Set-Cookie2")
|| headerKey.equalsIgnoreCase("Set-Cookie")
)
)
{
continue;
}

for (String headerValue : responseHeaders.get(headerKey)) {
try {
List<HttpCookie> cookies = HttpCookie.parse(headerValue);
for (HttpCookie cookie : cookies) {
if (shouldAcceptInternal(uri, cookie)) {
getCookieStore().add(uri, cookie);
}
}
} catch (IllegalArgumentException e) {
// invalid set-cookie header string
// no-op
}
}
}
}


/* ---------------- Private operations -------------- */

// to determine whether or not accept this cookie
private boolean shouldAcceptInternal(URI uri, HttpCookie cookie) {
try {
return policyCallback.shouldAccept(uri, cookie);
} catch (Exception ignored) { // pretect against malicious callback
return false;
}
}


/*
* path-matches algorithm, as defined by RFC 2965
*/
private boolean pathMatches(String path, String pathToMatchWith) {
if (path == pathToMatchWith)
return true;
if (path == null || pathToMatchWith == null)
return false;
if (path.startsWith(pathToMatchWith))
return true;

return false;
}


/*
* sort cookies with respect to their path: those with more specific Path attributes
* precede those with less specific, as defined in RFC 2965 sec. 3.3.4
*/
private List<String> sortByPath(List<HttpCookie> cookies) {
Collections.sort(cookies, new CookiePathComparator());

List<String> cookieHeader = new java.util.ArrayList<String>();
for (HttpCookie cookie : cookies) {
// Netscape cookie spec and RFC 2965 have different format of Cookie
// header; RFC 2965 requires a leading $Version="1" string while Netscape
// does not.
// The workaround here is to add a $Version="1" string in advance
if (cookies.indexOf(cookie) == 0 && cookie.getVersion() > 0) {
cookieHeader.add("$Version=\"1\"");
}

cookieHeader.add(cookie.toString());
}
return cookieHeader;
}


static class CookiePathComparator implements Comparator<HttpCookie> {
public int compare(HttpCookie c1, HttpCookie c2) {
if (c1 == c2) return 0;
if (c1 == null) return -1;
if (c2 == null) return 1;

// path rule only applies to the cookies with same name
if (!c1.getName().equals(c2.getName())) return 0;

// those with more specific Path attributes precede those with less specific
if (c1.getPath().startsWith(c2.getPath()))
return -1;
else if (c2.getPath().startsWith(c1.getPath()))
return 1;
else
return 0;
}
}
}

请注意,在我的例子中,我将 CookiePolicy 的默认值更改为 ACCEPT_ALL

2 在全局范围内,在运行任何线程之前,调用:

CookieHandler.setDefault(SessionCookieManager.getInstance());

3 当你的线程结束时,调用它内部:

SessionCookieManager.getInstance().clear();

再一次:不是我的想法,只是把它放在一起。所有功劳归功于 Javahttps://stackoverflow.com/users/1442259/nivs

关于java - 用于多线程的 CookieManager,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16305486/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com