Skip to main content

21.24. http.cookiejar — HTTP客户端的Cookie处理

源代码: Lib/http/cookiejar.py


http.cookiejar 模块定义了用于自动处理HTTP cookie的类。它对于访问需要小数据块(cookies)的Web站点有用,它通过来自Web服务器的HTTP响应在客户端机器上设置,然后在以后的HTTP请求中返回到服务器。

定期Netscape cookie协议和由 RFC 2965 定义的协议都被处理。默认情况下,RFC 2965处理被关闭。 RFC 2109 Cookie将被解析为Netscape Cookie,并根据“策略”生效,随后被视为Netscape或RFC 2965 Cookie。请注意,互联网上的绝大多数Cookie都是Netscape Cookie。 http.cookiejar 尝试遵循事实上的Netscape cookie协议(其与原始Netscape规范中阐述的协议大不相同),包括注意与RFC 2965一起引入的 max-ageport cookie属性。

注解

Set-CookieSet-Cookie2 报头(例如,domainexpires)中找到的各种命名参数通常被称为 attributes。要将它们与Python属性区分开来,此模块的文档将使用术语 cookie-attribute

模块定义了以下异常:

exception http.cookiejar.LoadError

FileCookieJar 的实例在未能从文件加载Cookie时引发此异常。 LoadErrorOSError 的一个子类。

在 3.3 版更改: LoadError是 OSError 的子类,而不是 IOError

提供以下类:

class http.cookiejar.CookieJar(policy=None)

policy 是实现 CookiePolicy 接口的对象。

CookieJar 类存储HTTP Cookie。它从HTTP请求中提取Cookie,并在HTTP响应中返回。必要时,CookieJar 实例会自动过期包含的Cookie。子类也负责从文件或数据库存储和检索Cookie。

class http.cookiejar.FileCookieJar(filename, delayload=None, policy=None)

policy 是实现 CookiePolicy 接口的对象。有关其他参数,请参阅相应属性的文档。

A CookieJar 可以从磁盘上的文件加载Cookie,也可以保存Cookie到磁盘上的文件。 Cookie是从命名文件加载的 ,直到调用 load()revert() 方法。此类的子类在 FileCookieJar子类和与Web浏览器的协作 部分中进行了说明。

class http.cookiejar.CookiePolicy

这个类负责决定每个cookie是否应该被接受/返回到服务器。

class http.cookiejar.DefaultCookiePolicy(blocked_domains=None, allowed_domains=None, netscape=True, rfc2965=False, rfc2109_as_netscape=None, hide_cookie2=False, strict_domain=False, strict_rfc2965_unverifiable=True, strict_ns_unverifiable=False, strict_ns_domain=DefaultCookiePolicy.DomainLiberal, strict_ns_set_initial_dollar=False, strict_ns_set_path=False)

构造函数参数只应作为关键字参数传递。 blocked_domains 是一系列域名,我们从不接受cookie,也不会返回cookie。 allowed_domains (如果不是 None),这是我们接受并返回Cookie的唯一域的序列。对于所有其他参数,请参阅 CookiePolicyDefaultCookiePolicy 对象的文档。

DefaultCookiePolicy 实现Netscape和RFC 2965 cookie的标准接受/拒绝规则。默认情况下,根据RFC 2965规则来处理RFC 2109 cookie(即,在版本cookie属性为1的 Set-Cookie 头中接收的cookie)。然而,如果RFC 2965处理被关闭或 rfc2109_as_netscapeTrue,则通过将 Cookie 实例的 version 属性设置为0,RFC 2109 cookie被 CookieJar 实例“降级”为Netscape cookie。DefaultCookiePolicy 还提供一些参数以允许一些精细调整政策。

class http.cookiejar.Cookie

此类表示Netscape,RFC 2109和RFC 2965 cookie。不希望 http.cookiejar 的用户构造他们自己的 Cookie 实例。相反,如果需要,在 CookieJar 实例上调用 make_cookies()

参见

模块 urllib.request

使用自动Cookie处理的网址打开。

模块 http.cookies

HTTP cookie类,主要用于服务器端代码。 http.cookiejarhttp.cookies 模块不依赖于彼此。

https://curl.haxx.se/rfc/cookie_spec.html

原始Netscape Cookie协议的规范。虽然这仍然是主要的协议,由所有主要浏览器(和 http.cookiejar)实施的“Netscape cookie协议”只是与 cookie_spec.html 中描绘的一个相似。

RFC 2109 - HTTP状态管理机制

由RFC 2965废弃。使用版本= 1的 Set-Cookie

RFC 2965 - HTTP状态管理机制

Netscape协议修复了错误。使用 Set-Cookie2 代替 Set-Cookie。不广泛使用。

http://kristol.org/cookie/errata.html

RFC 2965的未完成勘误表。

RFC 2964 - 使用HTTP状态管理

21.24.1. CookieJar和FileCookieJar对象

CookieJar 对象支持 iterator 协议对所包含的 Cookie 对象进行迭代。

CookieJar 有以下方法:

将正确的 Cookie 标题添加到 request

如果策略允许(即,CookieJarCookiePolicy 实例的 rfc2965hide_cookie2 属性分别为真和假),则在适当时也添加 Cookie2 报头。

request 对象(通常是 urllib.request..Request 实例)必须支持 urllib.request 所记录的方法 get_full_url()get_host()get_type()unverifiable()has_header()get_header()header_items()add_unredirected_header()origin_req_host 属性。

在 3.3 版更改: request 对象需要 origin_req_host 属性。依赖于已弃用的方法 get_origin_req_host() 已被删除。

CookieJar.extract_cookies(response, request)

从HTTP response 提取cookie,并将其存储在 CookieJar 中,策略允许。

CookieJar 将在 response 参数中查找允许的 Set-CookieSet-Cookie2 头,并存储cookie(根据 CookiePolicy.set_ok() 方法的批准)。

response 对象(通常是对 urllib.request.urlopen() 的调用的结果或类似的)应该支持 info() 方法,该方法返回 email.message.Message 实例。

request 对象(通常是 urllib.request.Request 实例)必须支持 urllib.request 记录的方法 get_full_url()get_host()unverifiable()origin_req_host 属性。请求用于设置cookie属性的默认值以及检查是否允许设置cookie。

在 3.3 版更改: request 对象需要 origin_req_host 属性。依赖于已弃用的方法 get_origin_req_host() 已被删除。

CookieJar.set_policy(policy)

设置要使用的 CookiePolicy 实例。

CookieJar.make_cookies(response, request)

response 对象提取的 Cookie 对象的返回序列。

有关 responserequest 参数所需的接口,请参阅 extract_cookies() 的文档。

如果政策表示可以这么做,请设置 Cookie

设置 Cookie,而不检查策略以查看是否应设置它。

CookieJar.clear([domain[, path[, name]]])

清除一些Cookie。

如果没有参数调用,请清除所有Cookie。如果给定一个参数,只有属于该 domain 的cookie将被删除。如果给定两个参数,那么将删除属于指定 domain 和URL path 的Cookie。如果给定三个参数,则删除具有指定 domainpathname 的cookie。

如果没有匹配的Cookie,则提升 KeyError

CookieJar.clear_session_cookies()

舍弃所有会话Cookie。

丢弃所有包含具有真正 discard 属性的cookie(通常是因为它们没有 max-ageexpires cookie属性,或者显式 discard cookie属性)。对于交互式浏览器,会话结束通常对应于关闭浏览器窗口。

注意,save() 方法不会保存会话cookie,除非你通过传递一个真正的 ignore_discard 参数来询问。

FileCookieJar 实现以下附加方法:

FileCookieJar.save(filename=None, ignore_discard=False, ignore_expires=False)

将Cookie保存到文件。

这个基类提出了 NotImplementedError。子类可以保留此方法未实现。

filename 是保存Cookie的文件的名称。如果未指定 filename,则使用 self.filename (其缺省值为传递给构造函数的值(如果有));如果 self.filenameNone,则 ValueError 被引发。

ignore_discard:保存即将设置为丢弃的Cookie。 ignore_expires:保存已过期的Cookie

如果文件已存在,则会被覆盖,从而擦除其包含的所有Cookie。保存的Cookie可以稍后使用 load()revert() 方法恢复。

FileCookieJar.load(filename=None, ignore_discard=False, ignore_expires=False)

从文件加载Cookie。

保留旧cookie,除非被新加载的cookie覆盖。

参数与 save() 一样。

命名文件必须是该类所理解的格式,否则将引发 LoadError。此外,可以引发 OSError,例如,如果文件不存在。

在 3.3 版更改: IOError 以前被提出,它现在是 OSError 的别名。

FileCookieJar.revert(filename=None, ignore_discard=False, ignore_expires=False)

清除所有Cookie并从已保存的文件重新加载Cookie。

revert() 可以提出与 load() 相同的例外。如果出现故障,对象的状态不会改变。

FileCookieJar 实例具有以下公共属性:

FileCookieJar.filename

保存Cookie的默认文件的文件名。此属性可以分配给。

FileCookieJar.delayload

如果为true,则从磁盘延迟加载Cookie。此属性不应分配给。这只是一个提示,因为这只会影响性能,而不是行为(除非磁盘上的cookie正在改变)。 CookieJar 对象可以忽略它。标准库中包含的 FileCookieJar 类都不会延迟加载Cookie。

21.24.2. FileCookieJar子类和与Web浏览器的协作

提供以下 CookieJar 子类用于读写。

class http.cookiejar.MozillaCookieJar(filename, delayload=None, policy=None)

FileCookieJar,可以Mozilla cookies.txt 文件格式加载和保存cookie到磁盘(也被Lynx和Netscape浏览器使用)。

注解

这会丢失有关RFC 2965 cookie以及有关新的或非标准的cookie属性(如 port)的信息。

警告

如果您的Cookie的损失/损坏不方便(有一些细微之处,可能会导致加载/保存往返程序中的文件略有更改),请在保存前备份您的Cookie。

还要注意,Mozilla运行时保存的Cookie会被Mozilla破坏。

class http.cookiejar.LWPCookieJar(filename, delayload=None, policy=None)

FileCookieJar 可以从与libwww-perl库的 Set-Cookie3 文件格式兼容的格式加载和保存cookie到磁盘。如果您想要将Cookie存储在可读的文件中,这很方便。

21.24.3. CookiePolicy对象

实现 CookiePolicy 接口的对象有以下方法:

CookiePolicy.set_ok(cookie, request)

返回布尔值,指示是否应从服务器接受cookie。

cookieCookie 实例。 request 是实现由 CookieJar.extract_cookies() 文档定义的接口的对象。

CookiePolicy.return_ok(cookie, request)

返回指示是否应将Cookie返回到服务器的布尔值。

cookieCookie 实例。 request 是实现由 CookieJar.add_cookie_header() 文档定义的接口的对象。

CookiePolicy.domain_return_ok(domain, request)

如果Cookie不应该返回,返回false,给定Cookie域。

这个方法是一个优化。它不需要检查每个cookie的特定域(这可能涉及读取许多文件)。从 domain_return_ok()path_return_ok() 返回真实,将所有的工作留给 return_ok()

如果 domain_return_ok() 对cookie域返回true,则为cookie路径调用 path_return_ok()。否则,从来不会为该Cookie域调用 path_return_ok()return_ok()。如果 path_return_ok() 返回true,则使用 Cookie 对象本身调用 return_ok() 以进行完全检查。否则,不会为该Cookie路径调用 return_ok()

请注意,每个 cookie 域都会调用 domain_return_ok(),而不仅仅是 request 域。例如,如果请求域是 "www.example.com",则可以用 ".example.com""www.example.com" 调用该函数。 path_return_ok() 也是如此。

request 参数是为 return_ok() 记录的。

CookiePolicy.path_return_ok(path, request)

如果Cookie不应该返回,返回false,给定cookie路径。

请参阅 domain_return_ok() 的文档。

除了实现上述方法外,CookiePolicy 接口的实现还必须提供以下属性,指示应使用哪些协议以及如何使用。所有这些属性可以分配给。

CookiePolicy.netscape

实现Netscape协议。

CookiePolicy.rfc2965

实现RFC 2965协议。

CookiePolicy.hide_cookie2

不要向请求添加 Cookie2 头(此头的存在表示服务器,我们了解RFC 2965 cookie)。

定义 CookiePolicy 类的最有用的方法是通过从 DefaultCookiePolicy 子类化并覆盖以上的一些或所有方法。 CookiePolicy 本身可以用作“空策略”,允许设置和接收任何和所有的cookie(这不太可能有用)。

21.24.4. DefaultCookiePolicy对象

实现接受和返回Cookie的标准规则。

包括RFC 2965和Netscape cookie。默认情况下,RFC 2965处理被关闭。

提供自己的策略的最简单的方法是重写这个类,并在重写的实现中调用它的方法,然后添加您自己的附加检查:

import http.cookiejar
class MyCookiePolicy(http.cookiejar.DefaultCookiePolicy):
    def set_ok(self, cookie, request):
        if not http.cookiejar.DefaultCookiePolicy.set_ok(self, cookie, request):
            return False
        if i_dont_want_to_store_this_cookie(cookie):
            return False
        return True

除了实现 CookiePolicy 接口所需的功能之外,此类允许您阻止和允许域设置和接收Cookie。还有一些严格的开关,允许你收紧相当松的Netscape协议规则一点点(以代价阻塞一些良性的cookie)。

提供域黑名单和白名单(默认都关闭)。只有不在黑名单中并且存在于白名单中的域(如果白名单是活动的)参与cookie设置和返回。使用 blocked_domains 构造函数参数,blocked_domains()set_blocked_domains() 方法(以及 allowed_domains 的相应参数和方法)。如果您设置了白名单,您可以将其设置为 None,再次将其关闭。

不以点开头的块或允许列表中的域必须等于要匹配的Cookie域。例如,"example.com" 匹配 "example.com" 的黑名单条目,但 "www.example.com" 不匹配。以点开始的域也由更具体的域匹配。例如,"www.example.com""www.coyote.example.com" 都与 ".example.com" 匹配(但是 "example.com" 本身不匹配)。 IP地址是一个例外,必须完全匹配。例如,如果blocked_domains包含 "192.168.1.2"".168.1.2",则阻止192.168.1.2,但不阻止193.168.1.2。

DefaultCookiePolicy 实现以下附加方法:

DefaultCookiePolicy.blocked_domains()

返回被阻止的域的序列(作为元组)。

DefaultCookiePolicy.set_blocked_domains(blocked_domains)

设置阻止域的顺序。

DefaultCookiePolicy.is_blocked(domain)

返回 domain 是否在设置或接收Cookie的黑名单上。

DefaultCookiePolicy.allowed_domains()

返回 None 或允许的域序列(作为元组)。

DefaultCookiePolicy.set_allowed_domains(allowed_domains)

设置允许的域或 None 的顺序。

DefaultCookiePolicy.is_not_allowed(domain)

返回 domain 是否不在设置或接收Cookie的白名单上。

DefaultCookiePolicy 实例具有以下属性,它们都从同名的构造函数参数初始化,并且可以全部分配给它们。

DefaultCookiePolicy.rfc2109_as_netscape

如果为true,请通过将 Cookie 实例的版本属性设置为0,将 CookieJar 实例降级为Netscape cookie,将RFC 2109 cookie(即,在版本cookie属性为1的 Set-Cookie 头中接收的cookie)降级为0.默认值为 None ,在这种情况下RFC 2109 cookie被降级,当且仅当RFC 2965处理被关闭。因此,RFC 2109 cookie默认降级。

一般严格开关:

DefaultCookiePolicy.strict_domain

不允许网站设置具有国家/地区代码顶级域(如 .co.uk.gov.uk.co.nz .etc)的双组件域。这是远非完美,不能保证工作!

RFC 2965协议严格开关:

DefaultCookiePolicy.strict_rfc2965_unverifiable

遵循关于不可验证事务的RFC 2965规则(通常,不可验证的事务是由重定向或对托管在另一个站点上的图像的请求导致的)。如果这是假的,Cookie是 never 在可验证性的基础上被阻止

Netscape协议严格开关:

DefaultCookiePolicy.strict_ns_unverifiable

对不可验证的事务应用RFC 2965规则,甚至对Netscape cookie。

DefaultCookiePolicy.strict_ns_domain

标记指示Netscape Cookie的域匹配规则的严格程度。请参阅下面的可接受值。

DefaultCookiePolicy.strict_ns_set_initial_dollar

忽略Set-Cookie中的Cookie:名称以 '$' 开头的标头。

DefaultCookiePolicy.strict_ns_set_path

不允许设置其路径不与路径匹配请求URI的Cookie。

strict_ns_domain 是标志的集合。它的值由一起构造(例如,DomainStrictNoDots|DomainStrictNonDomain 意味着两个标志都被设置)。

DefaultCookiePolicy.DomainStrictNoDots

设置Cookie时,“主机前缀”不能包含点(例如,www.foo.bar.com 无法为 .bar.com 设置Cookie,因为 www.foo 包含点)。

DefaultCookiePolicy.DomainStrictNonDomain

没有明确指定 domain cookie属性的Cookie只能返回到与设置cookie的域相等的域(例如,spam.example.com 不会从 example.com 返回没有 domain cookie属性的cookie)。

DefaultCookiePolicy.DomainRFC2965Match

设置Cookie时,需要完全的RFC 2965域匹配。

为方便起见,提供了以下属性,它们是上述标志的最有用的组合:

DefaultCookiePolicy.DomainLiberal

等于0(即所有上述Netscape域严格标志关闭)。

DefaultCookiePolicy.DomainStrict

相当于 DomainStrictNoDots|DomainStrictNonDomain

21.24.6. 例子

第一个示例显示了 http.cookiejar 的最常见用法:

import http.cookiejar, urllib.request
cj = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
r = opener.open("http://example.com/")

此示例说明了如何使用Netscape,Mozilla或Lynx Cookie打开URL(假定对于Cookie文件的位置使用Unix/Netscape惯例):

import os, http.cookiejar, urllib.request
cj = http.cookiejar.MozillaCookieJar()
cj.load(os.path.join(os.path.expanduser("~"), ".netscape", "cookies.txt"))
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
r = opener.open("http://example.com/")

下一个例子说明了 DefaultCookiePolicy 的使用。启用RFC 2965 Cookie,设置和返回Netscape Cookie时更严格的域名,并阻止某些域设置Cookie或返回:

import urllib.request
from http.cookiejar import CookieJar, DefaultCookiePolicy
policy = DefaultCookiePolicy(
    rfc2965=True, strict_ns_domain=Policy.DomainStrict,
    blocked_domains=["ads.net", ".ads.net"])
cj = CookieJar(policy)
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
r = opener.open("http://example.com/")