且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

“WindowsError: [错误 5] 访问被拒绝";使用 urllib2

更新时间:2022-11-30 18:19:55

看起来这是 Windows 证书存储不一致.httplib - 由 urllib2 内部调用 - 最近从无服务器证书验证更改为默认强制执行服务器证书验证.因此,您将在任何基于 urllibhttplib 并在您的用户配置文件中运行的 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 Authoritiescode> 在 certmgr.msc 中)但对于 ROOT 成功,这是正常的受信任根证书存储(请参阅问题评论).因此,我建议检查 certmgr:intermediate certificate authority 中的所有证书以获取最近添加的证书和/或 Windows 日志中的一般错误.在您的情况下发生的事情是 urllib2 内部调用 httplib 然后它尝试设置一个默认的 ssl 上下文并强制执行证书验证,并作为其中的一部分枚举受信任的通过调用 ssl.enum_certificates 来获取系统的证书锚点.此函数C中实现作为 _ssl_enum_certificates_impl 并在内部调用 WINAPI CertOpenSystemStoreCertEnumCertificatesInStore.对于证书存储位置 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:CertOpenSystemStoreLPTCSTR::'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 以不包含损坏的 CAcertstore 或完全禁用信任锚加载逻辑.(所有其他 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.