网站证书验证困惑:Bitstamp证书报错及自签名证书查找方法
解决SSL证书验证失败的困惑:urllib2、curl报错但openssl显示正常的问题
你遇到的情况挺典型的——用urllib2和curl访问www.bitstamp.net时都碰到证书验证失败,但openssl s_client却显示证书链都验证通过了,这确实容易让人懵。我来拆解下可能的原因和解决办法:
一、核心原因分析
这种不一致通常是因为不同工具使用的根证书存储库不一样:
openssl s_client默认可能用的是系统自带的根证书,或者你执行命令时隐含了特定证书配置;- 而Python的urllib2(尤其是旧版本)和curl可能依赖单独的证书存储,或者系统根证书库没有包含bitstamp证书链里的某个中间/自签名证书,这也是curl报错里提到的
self signed certificate in certificate chain的根源。
二、针对不同工具的解决办法
1. 解决curl的证书问题
你可以手动导出bitstamp的完整证书链,然后用这个证书文件来访问:
# 导出bitstamp的完整证书链到本地文件 openssl s_client -connect www.bitstamp.net:443 -showcerts </dev/null 2>/dev/null | sed -n '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p' > bitstamp_certs.pem # 使用导出的证书文件发起请求 curl --cacert bitstamp_certs.pem https://www.bitstamp.net
如果只是临时测试,也可以用-k参数跳过验证(注意:生产环境绝对不推荐这么做,会带来安全风险):
curl -k https://www.bitstamp.net
2. 解决Python urllib2的证书问题
旧版本的urllib2对SSL验证的支持不够灵活,你可以手动指定证书文件,或者改用更现代的requests库(推荐,它的SSL处理逻辑更友好):
方法一:用urllib2指定证书文件
import urllib2 # 使用刚才导出的bitstamp_certs.pem文件 cert_file = 'bitstamp_certs.pem' request = urllib2.Request('https://www.bitstamp.net') response = urllib2.urlopen(request, cafile=cert_file) print(response.read())
方法二:改用requests库(更简洁)
先安装requests:
pip install requests
然后通过指定证书或临时跳过验证来访问:
import requests # 指定证书文件发起请求 response = requests.get('https://www.bitstamp.net', verify='bitstamp_certs.pem') # 临时跳过验证(仅测试用,生产环境禁用) # response = requests.get('https://www.bitstamp.net', verify=False) print(response.text)
三、为什么openssl显示验证通过?
openssl s_client的验证逻辑相对宽松:如果证书链里的自签名中间证书能和服务器返回的证书形成完整链路,它会标记为验证通过。但curl和urllib2会严格检查整个链的所有证书是否都在本地信任的根证书列表里,当中间证书是自签名且未被信任时,就会抛出验证失败的错误。另外也有可能你的系统根证书库已经包含了这个自签名证书,但curl/urllib2使用的证书库没有同步更新。
内容的提问来源于stack exchange,提问作者Lightning Mcqueen
相关产品推荐
相关产品推荐

