更新时间:2022-11-30 18:19:55
看起来这是 Windows 证书存储不一致.httplib
- 由 urllib2
内部调用 - 最近从无服务器证书验证更改为默认强制执行服务器证书验证.因此,您将在任何基于 urllib
、httplib
并在您的用户配置文件中运行的 Python 脚本中遇到此问题.
It looks like this is a windows certificate store inconsistency. httplib
- which is internally called by urllib2
- recently changed from no server certificate validation to enforce server certificate validation by default. Therefore you'll encounter this problem in any python script that is based on urllib
, httplib
and running within your user profile.
也就是说,您的 Windows 证书存储似乎有问题.httplib
在尝试枚举指定证书存储的证书时失败 CA
certification authority
(显示为 Intermediate Certification Authorities
code> 在 certmgr.msc
中)但对于 ROOT
成功,这是正常的受信任根证书存储(请参阅问题评论).因此,我建议检查 certmgr:intermediate certificate authority
中的所有证书以获取最近添加的证书和/或 Windows 日志中的一般错误.在您的情况下发生的事情是 urllib2
内部调用 httplib
然后它尝试设置一个默认的 ssl 上下文并强制执行证书验证,并作为其中的一部分枚举受信任的通过调用 ssl.enum_certificates
来获取系统的证书锚点.此函数在C
中实现作为 _ssl_enum_certificates_impl
并在内部调用 WINAPI CertOpenSystemStore
和 CertEnumCertificatesInStore
.对于证书存储位置 CA
,它只是在两次 winapi 调用之一中失败,访问被拒绝.
That said, something seems to be very wrong with your windows certificate store. httplib
fails for you while trying to enumerate certificates for the named certificate stores CA
certification authority
(shows up as Intermediate Certification Authorities
in certmgr.msc
) but succeeds for ROOT
which is the normal trusted root certificate store (see comments to question). I'd therefore suggest to check all the certificates in certmgr:intermediate certificate authorities
for recently added certificates and/or the windows log for general errors.
What is going on in your case is that urllib2
internally calls httplib
which then tries to set up a default ssl context with certificate validation enforced and as part of this it enumerates the trusted certificate anchors of your system by calling ssl.enum_certificates
. This function is implemented in C
as _ssl_enum_certificates_impl
and internally calls WINAPIs CertOpenSystemStore
and CertEnumCertificatesInStore
. For the certificate store location CA
it just failes in one of the two winapi calls with an access denied.
如果你想进一步调试,你也可以尝试手动调用 WINAPI:CertOpenSystemStore
以LPTCSTR::'CA'
作为参数,并尝试从这一端调试它,尝试其他 Windows certstore 管理工具和/或致电微软支持寻求帮助.
If you want to further debug this you can also try to manually invoke the WINAPI:CertOpenSystemStore
with LPTCSTR::'CA'
as an argument and try to debug it from this side, try other windows certstore management tools and/or call microsoft support for asistance.
也有迹象表明其他人在连接该 api 调用时也遇到了类似的问题,请参阅谷歌:访问被拒绝 CertOpenSystemStore
There are also indications that others had similar problems while interfacing that api call, see google:access denied CertOpenSystemStore
如果您只是想让它工作而不修复根本原因,您可以尝试使用以下解决方法临时修补 _windows_cert_stores
以不包含损坏的 CA
certstore 或完全禁用信任锚加载逻辑.(所有其他 ssl.SSLContext
调用将在当前进程中修补)
If you just want to make it work without fixing the root cause you could just try to use the following workaround that temporarily patches the _windows_cert_stores
to not include the broken CA
certstore or to completely disable the trust-anchor loading logic. (all other ssl.SSLContext
invocations will be patched in the current process)
注意这会有效地禁用服务器证书验证.
Note that this effectively disables server certificate verification.
ssl.SSLContext._windows_cert_stores = ("ROOT",) # patch windows_cert_stores default to only include "ROOT" as "CA" is broken for you.
#ssl.SSLContext.load_default_certs = lambda s,x:None # alternative, fully NOP load_default_certs to do nothing instead.
ctx = ssl.create_default_context() # create new sslcontext, not veryfing any certificates, hostnames.
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
hdr = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11'}
req = Request('https://' + url, headers=hdr)
x = urlopen( req , context=ctx).read()
ssl.SSLContext._windows_cert_stores = ("ROOT","CA") # UNDO PATCH
我希望这些信息能帮助您解决问题.祝你好运.
I hope this information will help you resolve the issue. good luck.