在urllib3中使用证书

时间:2014-05-30 12:01:09

标签: python google-app-engine ssl

我是一个Python新手。我正在使用urllib3与api交谈。我之所以使用此而非请求的原因是我想在GAE上托管我的应用。我的应用程序使用证书。当我发布数据时,我收到以下错误:

TypeError: __init__() got an unexpected keyword argument 'cert_reqs'

如何在我的urlopen电话中加入证书?代码片段如下

CA_CERTS = ('client-2048.crt', 'client-2048.key')

http = urllib3.PoolManager()
r = http.urlopen('POST', url, body=payload, headers={'X-Application': '???', 'Content-Type': 'application/x-www-form-urlencoded'}, cert_reqs='REQUIRED', ca_certs=CA_CERTS)
print r.status, r.data

3 个答案:

答案 0 :(得分:3)

您可以直接下载到HTTPSConnectionPool级别:

from urllib3.connectionpool import HTTPSConnectionPool
conn = HTTPSConnectionPool('httpbin.org', ca_certs='/etc/pki/tls/cert.pem', cert_reqs='REQUIRED')

或者,更简单地或通过connection_from_url()辅助函数:

conn = urllib3.connection_from_url('https://httpbin.org', ca_certs='/etc/pki/tls/cert.pem', cert_reqs='REQUIRED')

请注意,ca_certs是用于验证远程服务器证书的证书包的文件名。使用cert_filekey_file将您的客户端证书提供给远程服务器:

conn = urllib3.connection_from_url('https://httpbin.org', cert_file='client-2048.crt', key_file='client-2048.key', ca_certs='/etc/pki/tls/cert.pem', cert_reqs='REQUIRED')

然后发出您的请求:

response = conn.request('POST', 'https://httpbin.org/post', fields={'field1':1234, 'field2':'blah'})
>>> print response.data
{
  "args": {},
  "data": "",
  "files": {},
  "form": {
    "field1": "1234",
    "field2": "blah"
  },
  "headers": {
    "Accept-Encoding": "identity",
    "Connection": "close",
    "Content-Length": "220",
    "Content-Type": "multipart/form-data; boundary=048b02ad15274fc485c2cb2b6a280034",
    "Host": "httpbin.org",
    "X-Request-Id": "92fbc1da-d83e-439c-9468-65d27492664f"
  },
  "json": null,
  "origin": "220.233.14.203",
  "url": "http://httpbin.org/post"
}

答案 1 :(得分:0)

您应将cert_reqs='REQUIRED'ca_certs=CA_CERTS args直接传递给PoolManager()实例。

因此可以将原始示例更改为此:

CA_CERTS = ('client-2048.crt', 'client-2048.key')

http = urllib3.PoolManager(cert_reqs='REQUIRED', ca_certs=CA_CERTS)

r = http.urlopen('POST', url, body=payload, headers={'X-Application': '???', 'Content-Type': 'application/x-www-form-urlencoded'})
print r.status, r.data

答案 2 :(得分:0)

在其他情况下,

通过User-Agent标头似乎有帮助

不确定这是否是常见的行为,但是当我使用自签名证书而不使用403 - Access denied执行HTTPS请求时,我的服务器将返回User-Agent错误。

忽略证书时(即使用空的ssl.SSLContext),不需要User-Agent标头,请求将成功。仅当passing a self-signed certificate使用ca_certs参数时,我才需要包含User-Agent

http = urllib3.PoolManager(cert_reqs='REQUIRED', ca_certs='/path/to/cacert.pem')
r = http.urlopen('GET', url, headers={'User-Agent': 'myapp/v0.1.0'})
print(r.data)

我找不到任何表明使用自签名证书时为何要求User-Agent的来源。关于这一点的任何澄清都非常欢迎。

详细了解User-Agent标头here