"WindowsError: [Error 5] Access is denied" using urllib2
"WindowsError: [Error 5] Access is denied" using urllib2
我在阅读带有 urllib2 的网站时收到 "WindowsError: [Error 5] Access is denied" 消息。
from urllib2 import urlopen, Request
from bs4 import BeautifulSoup
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)
soup = BeautifulSoup( urlopen( req ).read() )
完整的追溯是:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python27\lib\urllib2.py", line 154, in urlopen
return opener.open(url, data, timeout)
File "C:\Python27\lib\urllib2.py", line 431, in open
response = self._open(req, data)
File "C:\Python27\lib\urllib2.py", line 449, in _open
'_open', req)
File "C:\Python27\lib\urllib2.py", line 409, in _call_chain
result = func(*args)
File "C:\Python27\lib\urllib2.py", line 1240, in https_open
context=self._context)
File "C:\Python27\lib\urllib2.py", line 1166, in do_open
h = http_class(host, timeout=req.timeout, **http_conn_args)
File "C:\Python27\lib\httplib.py", line 1258, in __init__
context = ssl._create_default_https_context()
File "C:\Python27\lib\ssl.py", line 440, in create_default_context
context.load_default_certs(purpose)
File "C:\Python27\lib\ssl.py", line 391, in load_default_certs
self._load_windows_store_certs(storename, purpose)
File "C:\Python27\lib\ssl.py", line 378, in _load_windows_store_certs
for cert, encoding, trust in enum_certificates(storename):
WindowsError: [Error 5] Access is denied
我已经按照建议 here 从具有管理员权限的命令提示符中尝试 运行 脚本,但它没有解决问题。
关于如何解决这个错误有什么建议吗?
这看起来像是 windows 证书存储不一致。 httplib
- 由 urllib2
内部调用 - 最近从无服务器证书验证更改为默认强制执行服务器证书验证。因此,您将在基于用户配置文件中的 urllib
、httplib
和 运行 的任何 python 脚本中遇到此问题。
也就是说,您的 windows 证书库似乎出了点问题。 httplib
在尝试枚举命名证书存储 CA
certification authority
的证书时失败(在 certmgr.msc
中显示为 Intermediate Certification Authorities
),但 [=20] 成功=] 这是正常的受信任根证书存储(请参阅问题评论)。因此,我建议检查 certmgr:intermediate certificate authorities
中的所有证书以获取最近添加的证书 and/or 以及 windows 日志中的一般错误。
你的情况是 urllib2
内部调用 httplib
然后尝试设置默认的 ssl 上下文并强制执行证书验证,作为其中的一部分,它通过呼叫 ssl.enum_certificates
。此函数 is implemented 在 C
中作为 _ssl_enum_certificates_impl
并在内部调用 WINAPI CertOpenSystemStore
和 CertEnumCertificatesInStore
。对于证书存储位置 CA
,它只是在两个 winapi 调用之一中失败,访问被拒绝。
如果你想进一步调试它你也可以尝试 manually invoke 以 LPTCSTR::'CA'
作为参数的 WINAPI:CertOpenSystemStore
并尝试从这边调试它,尝试其他 windows certstore 管理工具 and/or 致电 Microsoft 支持寻求帮助。
也有迹象表明其他人在连接 api 调用时遇到了类似的问题,请参阅 google:access denied CertOpenSystemStore
如果您只是想让它工作而不修复根本原因,您可以尝试使用以下解决方法临时修补 _windows_cert_stores
以不包括损坏的 CA
certstore 或完全禁用信任锚加载逻辑。 (所有其他 ssl.SSLContext
调用将在当前进程中修补)
注意这会有效地禁用服务器证书验证。
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
希望这些信息能帮助您解决问题。祝你好运。
使用 Windows 证书库存在几个潜在问题。 (我发现 运行 您的代码来自没有完整用户配置文件的服务帐户,这几乎是不可能的)。原因有些复杂,但不值得进一步讨论,因为有更简单的解决方案。如前所述,关闭 SSL 验证是一种解决方法,但如果您关心所提供证书的有效性,则可能不是最好的方法。
只需使用独立的证书存储来完全避免这种情况。对于 Python,这是 certifi package, which is kept up to date. This is easily accessed from the python requests 包。对于最常见的 python 发行版
,两者都应该很容易访问
import requests
from bs4 import BeautifulSoup
url = "www.google.com"
hdr = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11'}
r = requests.get('https://' + url, headers=hdr, verify=True)
soup = BeautifulSoup(r.text)
请注意,requests.get() 将在无效地址、无法访问的站点和失败的证书验证时抛出异常。所以你要准备好抓住这些。当成功联系站点并验证证书但未找到页面(例如 404 错误)时,您不会收到异常。因此,您还应该在发出请求后检查 r.status_code==200。 (自动处理 30x 重定向,因此您不会将它们视为状态代码,除非您告诉它不要遵循它们。)为了清楚起见,示例代码中省略了此检查。
另请注意,您并未在此处明确引用 certifi 模块。如果已安装,requests 将使用它。如果未安装,requests 将使用一组更有限的内置根 CA。
我在阅读带有 urllib2 的网站时收到 "WindowsError: [Error 5] Access is denied" 消息。
from urllib2 import urlopen, Request
from bs4 import BeautifulSoup
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)
soup = BeautifulSoup( urlopen( req ).read() )
完整的追溯是:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python27\lib\urllib2.py", line 154, in urlopen
return opener.open(url, data, timeout)
File "C:\Python27\lib\urllib2.py", line 431, in open
response = self._open(req, data)
File "C:\Python27\lib\urllib2.py", line 449, in _open
'_open', req)
File "C:\Python27\lib\urllib2.py", line 409, in _call_chain
result = func(*args)
File "C:\Python27\lib\urllib2.py", line 1240, in https_open
context=self._context)
File "C:\Python27\lib\urllib2.py", line 1166, in do_open
h = http_class(host, timeout=req.timeout, **http_conn_args)
File "C:\Python27\lib\httplib.py", line 1258, in __init__
context = ssl._create_default_https_context()
File "C:\Python27\lib\ssl.py", line 440, in create_default_context
context.load_default_certs(purpose)
File "C:\Python27\lib\ssl.py", line 391, in load_default_certs
self._load_windows_store_certs(storename, purpose)
File "C:\Python27\lib\ssl.py", line 378, in _load_windows_store_certs
for cert, encoding, trust in enum_certificates(storename):
WindowsError: [Error 5] Access is denied
我已经按照建议 here 从具有管理员权限的命令提示符中尝试 运行 脚本,但它没有解决问题。
关于如何解决这个错误有什么建议吗?
这看起来像是 windows 证书存储不一致。 httplib
- 由 urllib2
内部调用 - 最近从无服务器证书验证更改为默认强制执行服务器证书验证。因此,您将在基于用户配置文件中的 urllib
、httplib
和 运行 的任何 python 脚本中遇到此问题。
也就是说,您的 windows 证书库似乎出了点问题。 httplib
在尝试枚举命名证书存储 CA
certification authority
的证书时失败(在 certmgr.msc
中显示为 Intermediate Certification Authorities
),但 [=20] 成功=] 这是正常的受信任根证书存储(请参阅问题评论)。因此,我建议检查 certmgr:intermediate certificate authorities
中的所有证书以获取最近添加的证书 and/or 以及 windows 日志中的一般错误。
你的情况是 urllib2
内部调用 httplib
然后尝试设置默认的 ssl 上下文并强制执行证书验证,作为其中的一部分,它通过呼叫 ssl.enum_certificates
。此函数 is implemented 在 C
中作为 _ssl_enum_certificates_impl
并在内部调用 WINAPI CertOpenSystemStore
和 CertEnumCertificatesInStore
。对于证书存储位置 CA
,它只是在两个 winapi 调用之一中失败,访问被拒绝。
如果你想进一步调试它你也可以尝试 manually invoke 以 LPTCSTR::'CA'
作为参数的 WINAPI:CertOpenSystemStore
并尝试从这边调试它,尝试其他 windows certstore 管理工具 and/or 致电 Microsoft 支持寻求帮助。
也有迹象表明其他人在连接 api 调用时遇到了类似的问题,请参阅 google:access denied CertOpenSystemStore
如果您只是想让它工作而不修复根本原因,您可以尝试使用以下解决方法临时修补 _windows_cert_stores
以不包括损坏的 CA
certstore 或完全禁用信任锚加载逻辑。 (所有其他 ssl.SSLContext
调用将在当前进程中修补)
注意这会有效地禁用服务器证书验证。
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
希望这些信息能帮助您解决问题。祝你好运。
使用 Windows 证书库存在几个潜在问题。 (我发现 运行 您的代码来自没有完整用户配置文件的服务帐户,这几乎是不可能的)。原因有些复杂,但不值得进一步讨论,因为有更简单的解决方案。如前所述,关闭 SSL 验证是一种解决方法,但如果您关心所提供证书的有效性,则可能不是最好的方法。
只需使用独立的证书存储来完全避免这种情况。对于 Python,这是 certifi package, which is kept up to date. This is easily accessed from the python requests 包。对于最常见的 python 发行版
,两者都应该很容易访问import requests
from bs4 import BeautifulSoup
url = "www.google.com"
hdr = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11'}
r = requests.get('https://' + url, headers=hdr, verify=True)
soup = BeautifulSoup(r.text)
请注意,requests.get() 将在无效地址、无法访问的站点和失败的证书验证时抛出异常。所以你要准备好抓住这些。当成功联系站点并验证证书但未找到页面(例如 404 错误)时,您不会收到异常。因此,您还应该在发出请求后检查 r.status_code==200。 (自动处理 30x 重定向,因此您不会将它们视为状态代码,除非您告诉它不要遵循它们。)为了清楚起见,示例代码中省略了此检查。
另请注意,您并未在此处明确引用 certifi 模块。如果已安装,requests 将使用它。如果未安装,requests 将使用一组更有限的内置根 CA。