我尝试使用wincertstore
将Internet Explorer(IE)证书传递给requests
以下载文件。我的代码是:
import requests
import wincertstore
certfile = wincertstore.CertFile()
certfile.addstore('CA')
certfile.addstore('ROOT')
certfile.addstore('foocert_node0')
certfile.addstore('foocert_node1')
certfile.addstore('foocert_node2')
url = 'https://portal.foo.com/blahblahblah'
r = requests.get(url, verify=certfile.name)
我得到的错误是:
SSLError: ("bad handshake: Error([('SSL routines', 'ssl3_read_bytes', 'sslv3 alert handshake failure')],)",)
客户端(我认为是指我试图从url
下载文件的网站,即foo.com)给了我一个包含3个节点的证书,这个节点已经加载到了IE中证书商店。不幸的是,客户端仅使用IE证书。
我不确定是否需要将我的客户端证书节点显式添加到certfile中,但不管怎样,我仍然会遇到同样的错误。
有趣的是,如果我只是将网址粘贴到IE窗口并点击返回,我会获得一个Windows安全/确认证书弹出窗口,一旦我接受,该文件就会下载。不幸的是,我尝试自动执行此过程(使用selenium
),因此我想要一个适用于requests
的解决方案。
我还尝试将客户端证书转换为pem,首先将Windows证书导出到pfx,然后使用以下代码:
import OpenSSL.crypto
import os
import requests
import ssl
def convertpfxtopem(certificate_pfx, password_pfx, certificate_pem):
f_pem = open(certificate_pem, 'wb')
pfx = open(certificate_pfx, 'rb').read()
p12 = OpenSSL.crypto.load_pkcs12(pfx, str.encode(password_pfx))
f_pem.write(OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, p12.get_privatekey()))
f_pem.write(OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, p12.get_certificate()))
ca = p12.get_ca_certificates()
if ca is not None:
for cert in ca:
f_pem.write(OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert))
f_pem.close()
return Trueurlfile = 'test.xlsx'
convertpfxtopem(certificate_pfx, password_pfx, certificate_pem)
r = requests.get(url, verify=certificate_pem)
如果我使用此代码,我会得到相同的SSLError。
我错过了什么?非常感谢您的协助。
答案 0 :(得分:0)
所以我正在寻找的解决方案比我意识到的要简单得多。原来curl已经使用了Windows证书库。所以从python / windows,这可以工作:
import subprocess
subprocess.call(['curl', '-O', '-J', url], cwd='Temp')
-O和-J标志在本地使用文件头中的名称保存文件,而cwd允许您将输出放在您选择的目录中(需要已经存在)。