【问题标题】:Python requests.post certificate verify failsPython requests.post 证书验证失败
【发布时间】:2015-09-16 14:37:48
【问题描述】:

我有一个 python 应用程序,它通过 HTTPS 连接到网页 (wikis.xxx.yyy) 以从中检索和解析数据。鉴于所需的证书链在浏览器中,我可以浏览网页(我的系统使用 Ubuntu 14.04 LTS)。

$ python --version
Python 2.7.6

连接调用:

data = requests.post(URL, data=payload) 

失败并出现以下错误:

requests.exceptions.SSLError: [Errno bad handshake] [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE', 'certificate verify failed')]

我不能使用verify=False,因为如果我这样做了,我会收到这个错误:

/usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/connectionpool.py:768: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.org/en/latest/security.html InsecureRequestWarning)

我尝试将验证中的证书作为客户端证书 (http://docs.python-requests.org/en/latest/user/advanced/) 传递:data = requests.post(radio_status_URL, data=payload, verify="/home/user/.cert/foo.pem") 但它没有连接,实际上也没有返回任何错误。

认为我需要将证书链安装到受信任的 Ubuntu CA 存储中,我按照以下说明进行操作:https://askubuntu.com/questions/73287/how-do-i-install-a-root-certificate 我添加的 foo.cert 证书格式如下:

-----BEGIN CERTIFICATE-----
<....>
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
<....>
-----END CERTIFICATE-----

使用 openssl 我可以看到证书链没问题,我可以连接到 wikis.xxx.yyy :-)

$ openssl s_client -CApath ~/.cert/ -connect wikis.xxx.yyy:443
CONNECTED(00000003)
depth=2 DC = local, DC = windows, CN = RIM Root CA MCA01YKF
verify return:1
depth=1 DC = net, DC = rim, CN = RIM Subordinate CA MCA03YKF
verify return:1
depth=0 C = CA, ST = Ontario, L = Waterloo, O = BlackBerry, OU = BTS Operations, CN = wikis.xxx.yyy, emailAddress = no-reply@xxx.yyy

verify return:1
---
Certificate chain
 0 s:/C=CA/ST=Ontario/L=Waterloo/O=BlackBerry/OU=BTS Operations/CN=wikis.xxx.yyy/emailAddress=no-reply@xxx.yyy
   i:/DC=net/DC=rim/CN=RIM Subordinate CA MCA03YKF
---
Server certificate
-----BEGIN CERTIFICATE-----
<...>
-----END CERTIFICATE-----
subject=/C=CA/ST=Ontario/L=Waterloo/O=BlackBerry/OU=BTS Operations/CN=wikis.xxx.yyy/emailAddress=no-reply@xxx.yyy
issuer=/DC=net/DC=rim/CN=RIM Subordinate CA MCA03YKF
---
No client certificate CA names sent
---
SSL handshake has read 1810 bytes and written 609 bytes
---
New, TLSv1/SSLv3, Cipher is RC4-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : RC4-SHA
    Session-ID: FFD3D3EAC3807427D2D5E5BB2D70F064E2BB14218A368676A3225FBC5E5F1078
    Session-ID-ctx: 
    Master-Key: 930FBFB110BFC861E06C6A27DEBB15C2524A86F7EFC56693F4E52BA33F0AD236E5182169039909EC1BB3DE89C4C96B2B
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1442413894
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)

所以它可以工作并给出 0 的 ret 代码。不幸的是,python 没有这样做,我不知道如何连接:-(

我该如何解决这个问题?

【问题讨论】:

  • 只是为了澄清一点:verify=False 实际上并没有从网页返回信息(尽管有警告),但由于中间人攻击而非常不鼓励。
  • r=requests.post("https://httpbin.org/post") 是否适合您?
  • 它确实返回了一些东西:{ "args": {}, "data": "", "files": {}, "form": { "os_password": "YYYYYYY", "os_username ": "XXXXXXX" }, "headers": { "Accept": "/", "Accept-Encoding": "gzip, deflate", "Content-Length": "43", "内容类型”:“应用程序/x-www-form-urlencoded”,“主机”:“httpbin.org”,“用户代理”:“python-requests/2.7.0 CPython/2.7.6 Linux/3.16. 0-44-generic" }, "json": null, "origin": "208.93.78.35", "url": "httpbin.org/post" }

标签: python ssl https python-requests


【解决方案1】:

从您的上一个测试案例中可以看出 wikis.xxx.yyy 使用 TLSv1.2,但是 Requests 模块需要稍作修改才能使用它。

请参考这篇文章: https://lukasa.co.uk/2013/01/Choosing_SSL_Version_In_Requests/

还有一个很好的插件可以做到这一点: https://toolbelt.readthedocs.org/en/latest/user.html#ssladapter

顺便说一句,如果你安装了 urllib3,Requests 会使用它,但是 urllib3 直到现在还不支持 TLS v1.2。

【讨论】:

    猜你喜欢
    • 2021-11-26
    • 1970-01-01
    • 2015-08-26
    • 2020-12-15
    • 2013-09-30
    • 1970-01-01
    • 2012-03-15
    • 2021-03-02
    • 2016-05-19
    相关资源
    最近更新 更多