【HttpClient4.5中文教程】十一. 状态管理(Cookie相关)

x33g5p2x  于2021-12-28 转载在 其他  
字(5.3k)|赞(0)|评价(0)|浏览(564)

原始的 HTTP 是被设计为无状态的,面向请求/响应的协议,没有特别对一些逻辑相关的请求/响应交换的设置会话状态。 由于 HTTP 协议变得越来越普及和受欢迎,越来越多的从前没有打算使用它的系统也开始为应用程序来使用它,比如作为电子商务应用程序的传输。因此,支持状态管理就变得非常必要了。

网景公司,一度成为 Web 客户端和服务器软件开发者的领导方向,在它们基于专有规范的产品中实现了对 HTTP 状态管理的支持。 之后,网景公司试图通过发布规范草案来规范这种机制。 它们的努力通过 RFC 标准跟踪促成了这些规范定义。然而,在很多应用程序中的状态管理仍然基于网景公司的草案而不兼容官方的规范。 很多主要的Web浏览器开发者觉得有必要保留那些极大促进应用程序兼容性的标准草案。

Cookie 是 HTTP 代理和目标服务器可以交流保持会话的状态信息的令牌或小的数据包。网景公司的工程师把它称为“魔法小甜饼”("magic cookie"),这个名字好像有粘性一样。
HttpClient 使用 Cookie 接口来代表抽象的 cookie 令牌。 HTTP中简单形式中的cookie是名/值对。 通常一个 HTTP 的 cookie 也包含一些属性,比如版本号,合法的域名,指定 cookie 应用所在的源服务器URL路径的子集, cookie 的最长有效时间。
SetCookie接口代表由源服务器发送给HTTP代理的响应中的首部Set-Cookie,它用来维持一个对话状态。
ClientCookie接口和它指定的方法扩展了Cookie。比如:能够取回被源服务器定义的原始cookie。这对生成 Cookie 首部很重要,因为一些 cookie规范需要Cookie 首部应该包含特定的属性,这些属性只能在 Set-Cookie 头部中指定。

下面是客户端创建cookie对象的例子:

BasicClientCookie cookie = new BasicClientCookie("name", "value");
// Set effective domain and path attributes
cookie.setDomain(".mycompany.com");
cookie.setPath("/");
// Set attributes exactly as sent by the server
cookie.setAttribute(ClientCookie.PATH_ATTR, "/");
cookie.setAttribute(ClientCookie.DOMAIN_ATTR, ".mycompany.com");

2.cookie详解

CookieSpec接口代表一个管理cookie的规范,cookie管理规范是强制的。
·解析Set-Cookie头部规则
·分析验证cookie规则
·用给定的主机名,端口号,和原路径格式化Cookie首部

HttpClient附带了几个CookieSpec的实现

Standard strict:State management policy compliant with the syntax and semantics of the wellbehaved profile defined by RFC 6265, section 4.

Standard:State management policy compliant with a more relaxed profile defined by RFC
6265, section 4 intended for interoperability with existing servers that do not conform to the well
behaved profile.

Netscape draft (obsolete):This policy conforms to the original draft specification published
by Netscape Communications. It should be avoided unless absolutely necessary for compatibility
with legacy code.

RFC 2965 (obsolete):State management policy compliant with the obsolete state management
specification defined by RFC 2965. Please do not use in new applications.--->已废弃

RFC 2109 (obsolete):State management policy compliant with the obsolete state management
specification defined by RFC 2109. Please do not use in new applications--->已废弃

Browser compatibility (obsolete):This policy strives to closely mimic the (mis)behavior of
older versions of browser applications such as Microsoft Internet Explorer and Mozilla FireFox.
Please do not use in new applications.--->已废弃

Default:Default cookie policy is a synthetic policy that picks up either RFC 2965, RFC 2109
or Netscape draft compliant implementation based on properties of cookies sent with the HTTP
response (such as version attribute, now obsolete). This policy will be deprecated in favor of the
standard (RFC 6265 compliant) implementation in the next minor release of HttpClient.

Ignore cookies:所有的cookie将会被忽略

在新程序中,强烈建议使用Standard或Standard strict策略。废弃的规范仅应该使用在遗留项目中。下一个HttpClient版本将不会支持废弃的规范。

3.选择cookie策略

Cookie策略能够能够在HTTP客户端设置,如果需要的话,能够在HTTP请求中被重写(覆盖)。

RequestConfig globalConfig = RequestConfig.custom()
    .setCookieSpec(CookieSpecs.DEFAULT)
    .build();
CloseableHttpClient httpclient = HttpClients.custom()
    .setDefaultRequestConfig(globalConfig)
    .build();
RequestConfig localConfig = RequestConfig.copy(globalConfig)
    .setCookieSpec(CookieSpecs.STANDARD_STRICT)
.build();
HttpGet httpGet = new HttpGet("/");
httpGet.setConfig(localConfig);

4.自定义cookie策略

为了实现自定义的cookie策略你必须创建一个CookieSpec的实现,创建一个CookieSpecProvider的实现,用它来创建和初始化自定义规范的实例、和HttpClient注册工厂。一旦自定义的规范被注册,它将会和标准cookie规范一样被使用。

PublicSuffixMatcher publicSuffixMatcher = PublicSuffixMatcherLoader.getDefault();
Registry<CookieSpecProvider> r = RegistryBuilder.<CookieSpecProvider>create()
   .register(CookieSpecs.DEFAULT,new DefaultCookieSpecProvider(publicSuffixMatcher))
   .register(CookieSpecs.STANDARD,newRFC6265CookieSpecProvider(publicSuffixMatcher))
   .register("easy", new EasySpecProvider())
   .build();
RequestConfig requestConfig = RequestConfig.custom()
   .setCookieSpec("easy")
   .build();
   CloseableHttpClient httpclient = HttpClients.custom()
   .setDefaultCookieSpecRegistry(r)
   .setDefaultRequestConfig(requestConfig)
   .build();

5.Cookie 持久化

HttpClient能够使用任何实现了CookieStore接口的物理cookie。默认的CookieStore实现类被称为BasicCookieStore,它的内部是使用java.util.ArrayList的简单实现的。当容器进行垃圾回收时,储存在BasicClientCookie中的对象就会丢失。如果必要的话,使用者可以提供一个复杂的实现。

// Create a local instance of cookie store
CookieStore cookieStore = new BasicCookieStore();
// Populate cookies if needed
BasicClientCookie cookie = new BasicClientCookie("name", "value");
cookie.setDomain(".mycompany.com");
cookie.setPath("/");
cookieStore.addCookie(cookie);
// Set the store
CloseableHttpClient httpclient = HttpClients.custom().setDefaultCookieStore(cookieStore)
   .build();

6.HTTP状态管理和执行上下文

在一个HTTP执行请求的过程中,HttpClient向执行上下文中添加了下面的状态管理对象
Lookup实例代表了真实的cookie详细记录,这个属性的值设置在本地上下文中,优先于默认的。
CookieSpec实例代表了真实的cookie规范
CookieOrigin实例代表了当前的原服务器的详情
CookieStore实例代表了当前的cookie store,这个属性的值设置在本地上下文中而优先于默认的。

在请求执行之前,本地的HttpContext对象能够定制HTTP状态管理上下文,或者在请求执行后检查它的状态。你可以使用分离的上下文以便实现每个用户(或每个线程)的状态管理。cookie规范记录、cookie store定义在本地的上下文中优先于那些在HTTP客户端设置的默认的上下文。

CloseableHttpClient httpclient = <...>

Lookup<CookieSpecProvider> cookieSpecReg = <...>
CookieStore cookieStore = <...>

HttpClientContext context = HttpClientContext.create();
context.setCookieSpecRegistry(cookieSpecReg);
context.setCookieStore(cookieStore);
HttpGet httpget = new HttpGet("http://somehost/");
CloseableHttpResponse response1 = httpclient.execute(httpget, context);
<...>
// Cookie origin details
CookieOrigin cookieOrigin = context.getCookieOrigin();
// Cookie spec used
CookieSpec cookieSpec = context.getCookieSpec();

相关文章