Contents

Apache HttpClient 发送自定义cookie

1. 概述

本教程将重点介绍如何使用 Apache HttpClient 发送自定义 Cookie

如果您想更深入地挖掘并学习可以使用 HttpClient 做的其他很酷的事情 - 前往主要的HttpClient教程

2. 在HttpClient上配置Cookie管理

2.1. HttpClient 4.3

在较新的 HttpClient 4.3 中,我们将利用 fluent builder API 负责构建和配置客户端。

首先,我们需要创建一个 cookie 存储并在存储中设置我们的示例 cookie:

BasicCookieStore cookieStore = new BasicCookieStore();
BasicClientCookie cookie = new BasicClientCookie("JSESSIONID", "1234");
cookie.setDomain(".github.com");
cookie.setPath("/");
cookieStore.addCookie(cookie);

然后,我们可以使用*setDefaultCookieStore()*方法在 HttpClient 上设置这个 cookie 存储并发送请求:

@Test
public void whenSettingCookiesOnTheHttpClient_thenCookieSentCorrectly() 
  throws ClientProtocolException, IOException {
    BasicCookieStore cookieStore = new BasicCookieStore();
    BasicClientCookie cookie = new BasicClientCookie("JSESSIONID", "1234");
    cookie.setDomain(".github.com");
    cookie.setPath("/");
    cookieStore.addCookie(cookie);
    HttpClient client = HttpClientBuilder.create().setDefaultCookieStore(cookieStore).build();
    final HttpGet request = new HttpGet("http://www.github.com");
    response = client.execute(request);
    assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
}

一个非常重要的元素是在 cookie 上设置的域——如果没有设置正确的域,客户端根本不会发送 cookie! 此外,根据您使用的确切版本,您可能还需要设置:

cookie.setAttribute(ClientCookie.DOMAIN_ATTR, "true");

2.2. HttpClient 4.3之前

对于旧版本的 HttpClient(4.3 之前)——cookie 存储直接在HttpClient上设置:

@Test
public void givenUsingDeprecatedApi_whenSettingCookiesOnTheHttpClient_thenCorrect() 
  throws ClientProtocolException, IOException {
    BasicCookieStore cookieStore = new BasicCookieStore();
    BasicClientCookie cookie = new BasicClientCookie("JSESSIONID", "1234");
    cookie.setDomain(".github.com");
    cookie.setPath("/");
    cookieStore.addCookie(cookie);
    DefaultHttpClient client = new DefaultHttpClient();
    client.setCookieStore(cookieStore);
    HttpGet request = new HttpGet("http://www.github.com");
    response = client.execute(request);
    assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
}

除了构建客户端的方式之外,与前面的示例没有其他区别。

3. 在请求上设置Cookie

如果无法在整个 HttpClient 上设置 cookie,我们可以使用HttpContext类单独配置带有 cookie 的请求:

@Test
public void whenSettingCookiesOnTheRequest_thenCookieSentCorrectly() 
  throws ClientProtocolException, IOException {
    BasicCookieStore cookieStore = new BasicCookieStore();
    BasicClientCookie cookie = new BasicClientCookie("JSESSIONID", "1234");
    cookie.setDomain(".github.com");
    cookie.setPath("/");
    cookieStore.addCookie(cookie);
    instance = HttpClientBuilder.create().build();
    HttpGet request = new HttpGet("http://www.github.com");
    HttpContext localContext = new BasicHttpContext();
    localContext.setAttribute(HttpClientContext.COOKIE_STORE, cookieStore);
    // localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore); // before 4.3
    response = instance.execute(request, localContext);
    assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
}

4.在低级请求上设置Cookie

在 HTTP 请求上设置 cookie 的低级替代方法是将其设置为原始 Header:

@Test
public void whenSettingCookiesOnARequest_thenCorrect() 
  throws ClientProtocolException, IOException {
    instance = HttpClientBuilder.create().build();
    HttpGet request = new HttpGet("http://www.github.com");
    request.setHeader("Cookie", "JSESSIONID=1234");
    response = instance.execute(request);
    assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
}

这当然比使用内置 cookie 支持更容易出错。例如,请注意在这种情况下我们不再设置域——这是不正确的。