44

我有一个返回多个 cookie 的服务器请求,如下所示:

在此处输入图像描述

这就是我将这些 cookie 存储到 cookieManager 的方式:

HttpURLConnection connection = ... ;
static java.net.CookieManager msCookieManager = new java.net.CookieManager();
msCookieManager.put(COOKIES_URI, connection.getHeaderFields());

这就是我将这些 cookie 添加到下一个连接的方式:

connection.setRequestProperty("Cookie", 
  msCookieManager.getCookieStore().get(COOKIES_URI).toString());

这是从 cookieManager 获取 cookie 的正确方法吗?我很确定有更好的方法......

4

5 回答 5

108

好的,正确的做法是这样的:

从响应头中获取 Cookie 并将它们加载到 cookieManager 中:

static final String COOKIES_HEADER = "Set-Cookie";
HttpURLConnection connection = ... ;
static java.net.CookieManager msCookieManager = new java.net.CookieManager();

Map<String, List<String>> headerFields = connection.getHeaderFields();
List<String> cookiesHeader = headerFields.get(COOKIES_HEADER);

if (cookiesHeader != null) {
    for (String cookie : cookiesHeader) {
        msCookieManager.getCookieStore().add(null,HttpCookie.parse(cookie).get(0));
    }               
}

从 cookieManager 获取 Cookie 并将它们加载到连接中:

if (msCookieManager.getCookieStore().getCookies().size() > 0) {
    // While joining the Cookies, use ',' or ';' as needed. Most of the servers are using ';'
    connection.setRequestProperty("Cookie",
    TextUtils.join(";",  msCookieManager.getCookieStore().getCookies()));    
}
于 2013-04-23T14:16:28.160 回答
52

几天来我一直在搜索/尝试解决我的问题:即使成功登录后也无法访问受保护的网络资源

我在 iOS 上创建了相同的应用程序并没有遇到同样的问题,因为 NSUrlConnection 在幕后为我们进行了 cookie 维护。在 Android 上,我尝试手动添加 cookie

connection.setRequestProperty("Cookie", "PHPSESSID=str_from_server")

没有任何运气。

最后我读到了这个

并在我的应用程序开头的某处添加了以下两行:

CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);

现在一切正常。

于 2014-02-11T16:33:05.787 回答
3

@David 的回答是最好的。维护本地 CookieManager 并手动写入和读取与此 cookie 管理器关联的 cookie 存储是最简单的。

此代码将响应中的 Cookie 加载到 cookie 管理器中:

/**
 * Gets Cookies from the response header and loads them into cookie manager
 *
 * @param conn          instance of {@link HttpURLConnection} object
 * @param cookieManager the cookie manager({@link CookieManager} instance) in which the cookies are to be loaded<p>In case a null object is passed, the function will not perform any action and return back to the caller. </p>
 */
public static void loadResponseCookies(@Nullable HttpURLConnection conn,@Nullable CookieManager cookieManager) {

    //do nothing in case a null cokkie manager object is passed
    if (cookieManager == null || conn == null){
        return;
    }

    List<String> cookiesHeader = conn.getHeaderFields().get(COOKIES_HEADER);
    if (cookiesHeader != null) {
        for (String cookieHeader : cookiesHeader) {
            List<HttpCookie> cookies;
            try {
                cookies = HttpCookie.parse(cookieHeader);
            } catch (NullPointerException e) {
                log.warn(MessageFormat.format("{0} -- Null header for the cookie : {1}",conn.getURL().toString(), cookieHeader.toString()));
                //ignore the Null cookie header and proceed to the next cookie header
                continue;
            }

            if (cookies != null) {
                Debug("{0} -- Reading Cookies from the response :", conn.getURL().toString());
                for (HttpCookie cookie : cookies) {
                    Debug(cookie.toString());
                }
                if (cookies.size() > 0) {
                    cookieManager.getCookieStore().add(null, HttpCookie.parse(cookieHeader).get(0));
                }
            }
        }
    }
}

此代码使用与 cookie 管理器关联的 cookie 填充 HttpUrlConnection 对象:

public void populateCookieHeaders(HttpURLConnection conn) {

    if (this.cookieManager != null) {
        //getting cookies(if any) and manually adding them to the request header
        List<HttpCookie> cookies = this.cookieManager.getCookieStore().getCookies();

        if (cookies != null) {
            if (cookies.size() > 0) {
                Debug("{0} -- Adding Cookie Headers : ", url.toString());
                for (HttpCookie cookie : cookies) {
                    Debug(cookie.toString(), null);
                }

                //adding the cookie header
                conn.setRequestProperty(COOKIE_REQUEST_HEADER, StringUtils.join(cookies, ";"));
            }
        }
    }
}

这是处理 cookie 的最线程安全的方法。

我尝试使用 threadlocal cookiestore 和 CookieManager 的扩展。这些方法都不适用于我的情况。

于 2016-05-30T11:53:09.880 回答
1

其他答案适合他们的上下文,但没有人说显而易见的:CookieHandler 在大多数情况下会自动处理您的 cookie。如果只是维护从一个请求到下一个请求的 cookie——例如维护一个服务器会话——那么这行代码就足够了:

CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));

确保在您第一次使用 UrlConnection 请求之前运行一次。

现在我自己进行零 cookie 管理,并且我的所有服务器会话数据从请求到请求都得到完美维护。

我疯了吗?为什么互联网对此保持沉默?我什至无法在文档中找到它。

于 2020-09-23T19:39:21.903 回答
0

使用java.net.HttpURLConnection和 groovy,只需添加URLConnection#addRequestProperty(String key, String value)内部with闭包。

import java.net.HttpURLConnection

HttpURLConnection createRequest(String chatRequestBody) {
    HttpURLConnection httpChatRequest = new URL("${endpoint}").openConnection() as HttpURLConnection

    httpChatRequest.with {
        doOutput = true
        requestMethod = 'POST'

        //headers
        addRequestProperty("Content-Type", "application/json")
        addRequestProperty("Client-Platform", "android")

        //cookies
        addRequestProperty("Cookie", "cookie_key1=cookie_value1,cookie_key2=cookie_value2")

        getOutputStream().write(chatRequestBody.getBytes("UTF-8"))
    }
    httpChatRequest
}
于 2017-11-08T01:28:04.577 回答