[英]python requests verify SSL certificate
我正在嘗試從受SSL保護的API中提取數據。 我寫了一個python腳本來提取數據。 事先,我必須將.p12文件轉換為openSSL證書。 當我使用以下代碼時,它可以正常工作:
# ----- SCRIPT 1 -----
def pfx_to_pem(pfx_path, pfx_password):
''' Decrypts the .pfx file to be used with requests. '''
with tempfile.NamedTemporaryFile(suffix='.pem') as t_pem:
f_pem = open(t_pem.name, 'wb')
pfx = open(pfx_path, 'rb').read()
p12 = OpenSSL.crypto.load_pkcs12(pfx, pfx_password)
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()
yield t_pem.name
# read some config
with open('config.json') as config_json:
config = json.load(config_json)
api_url = config['api_url']
cert = config['cert']
cert_pem_path = cert['file']
cert_key_file = cert['pass']
# make the request
with pfx_to_pem(cert_pem_path, cert_key_file) as cert:
r = requests.get(api_url, cert = cert)
因為我還使用相同的功能對服務器驗證Flask Web服務,所以我將cert文件分為三個文件:
# ----- SCRIPT 1 -----
# get certificate
f_pem.write(OpenSSL.crypto.dump_certificate(
OpenSSL.crypto.FILETYPE_PEM, p12.get_certificate())
)
# get keyfile
f_key.write(OpenSSL.crypto.dump_privatekey(
OpenSSL.crypto.FILETYPE_PEM, p12.get_privatekey())
)
# get CA_BUNDLE
ca = p12.get_ca_certificates()
if ca is not None:
for cert in ca:
f_ca.write(
OpenSSL.crypto.dump_certificate(
OpenSSL.crypto.FILETYPE_PEM, cert
))
然后,我使用以下代碼運行Web服務:
# ----- SCRIPT 2 -----
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
context.verify_mode = ssl.CERT_REQUIRED
context.load_verify_locations(cert_ca)
context.load_cert_chain(cert_pem, cert_key)
app.run(ssl_context = context, host = '0.0.0.0')
並將請求調用更改為
# ----- SCRIPT 1 -----
r = requests.get(api_url, cert = (cert_pem, cert_key), verify = cert_ca)
嘗試從API提取數據時出現錯誤
requests.exceptions.SSLError: HTTPSConnectionPool(host='some.host', port=443): Max retries exceeded with url: /some/path/var?ID=xxxxxx (Caused by SSLError(SSLError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:847)'),))
問題1:創建CA_BUNDLE時我做錯了什么?
問題2:我是否正確處理了Web服務的創建? 我的目標是針對保存數據的服務器驗證我的服務器,以最終能夠通過推送請求接收數據。
編輯:當連接到我的Web服務(在瀏覽器中)時,盡管我將.p12證書導入到我的瀏覽器中,但由於證書無效,我收到連接不安全的警告。
因此,我使用了請求和json庫來調用API,就我而言,我可以設置請求以忽略證書,這樣可以快速解決我的問題
requests.get(url, headers=headers, verify=False)
參數verify = False忽略證書,但是在您運行代碼時,它將在輸出中顯示警告消息,提示證書錯誤,因此您可以添加另一段代碼以免顯示請求警告:
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
我知道這不能回答您的問題,但是也許您可以嘗試看看如果沒有證書,您是否可以毫無問題地獲取信息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.