在寫接口請求模擬測試時遇到https接口,按照日常思維參考http接口一樣直接上requests。
一切准備妥當后,運行腳本。。。。神馬情況,提示ssl錯誤
SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1056)'))
遇到問題就要解決,
第一次嘗試:
根據提示去google了一番,總結出需要安裝requests[security]庫
pip install requests[security]
會安裝三個security相關的package:pyopenssl cryptography idna
繼續執行腳本。。。what,依然提示ssl錯誤
SSLError("bad handshake: Error([('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')])")
心理感覺很欣慰,至少報錯內容不一樣了,繼續排錯,這次提示證書校驗失敗,可想而知是證書不對,那就先正確的證書
第二次嘗試:
因為本機開了charles做代理,所以自然想到下載charles證書
將證書保存到本地。
證書弄好了,要怎么要加到請求中?查看requests源碼
看到如下這段注解 :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair.
修改requests請求
requests.request("POST", url, headers=headers, data=payload, cert='/charles/charles-ssl-proxying-certificate.pem')
繼續請求腳本。。。心里有一萬只神馬東西在奔騰,依然ssl錯誤
OpenSSL.SSL.Error: [('PEM routines', 'get_name', 'no start line'), ('SSL routines', 'SSL_CTX_use_PrivateKey_file', 'PEM lib')]
難道是姿勢不對。。。
第三次嘗試:
回頭繼續看requests源碼
有如下一段注解: :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use. Defaults to ``True``. verify可以是boolean值也可以是一個string類型的文件路徑
於是嘗試修改requests請求,心理默默祈求上天眷顧可憐的小羊吧
requests.request("POST", url, headers=headers, data=payload, verify='/charles/charles-ssl-proxying-certificate.pem')
哈哈哈大笑三聲,終於搞定了。
回過頭來分析一下為什么要使用verify:
verify的解釋大概是說:是否校驗服務器的TSL證書。因為我們是走charles代理,對於腳本來說charles就是服務器,所以需要使用verify參數。
cert參數只有在我們自己實現ssl客戶端,並且生成證書文件時使用。
最后注意一下,如果關掉代理情,不需要使用verify參數。使用會出錯,因為此時服務端是真實服務器。