使用以下代码,当我使用异步Cannot connect to host ...:443 ssl:True
时,我得到aiohttp
。当我使用同步requests
时,它会成功。
whitehouse.gov
链接失败,但google.com
成功执行异步和同步情况。
出了什么问题?这是在FreeBSD8上的python 3.4.2,aiohttp 0.14.4,请求2.5.3
import asyncio
import aiohttp
import requests
urls = [
'http://www.whitehouse.gov/cea/',
'http://www.whitehouse.gov/omb',
'http://www.google.com']
def test_sync():
for url in urls:
r = requests.get(url)
print(r.status_code)
def test_async():
for url in urls:
try:
r = yield from aiohttp.request('get', url)
except aiohttp.errors.ClientOSError as e:
print('bad eternal link %s: %s' % (url, e))
else:
print(r.status)
if __name__ == '__main__':
print('async')
asyncio.get_event_loop().run_until_complete(test_async())
print('sync')
test_sync()
这个输出是:
async
bad eternal link http://www.whitehouse.gov/cea: Cannot connect to host www.whitehouse.gov:443 ssl:True
bad eternal link http://www.whitehouse.gov/omb: Cannot connect to host www.whitehouse.gov:443 ssl:True
200
sync
200
200
200
答案 0 :(得分:9)
我怀疑您的计算机上的证书验证链已损坏。 在Ubuntu上,一切正常,正如@dano所说。
无论如何,您可以通过创建自定义g.draw((Shape) new Rectangle( x, y, width, height));
实例来禁用ssl验证:
Connector
BTW,import asyncio
import aiohttp
urls = [
'http://www.whitehouse.gov/cea/',
'http://www.whitehouse.gov/omb',
'http://www.google.com']
def test_async():
connector = aiohttp.TCPConnector(verify_ssl=False)
for url in urls:
try:
r = yield from aiohttp.request('get', url, connector=connector)
except aiohttp.errors.ClientOSError as e:
print('bad eternal link %s: %s' % (url, e))
else:
print(r.status)
if __name__ == '__main__':
print('async')
asyncio.get_event_loop().run_until_complete(test_async())
库附带自己的证书包。也许我们需要为aiohttp做同样的事情?
答案 1 :(得分:0)
请勿使用此应答,因为这等同于禁用证书检查。
Le Hibou在评论中指出,ssl.Purpose.CLIENT_AUTH
用于在服务器端对客户端进行身份验证。
此值表明上下文可以用于验证Web客户端(因此,它将用于创建服务器端套接字)。
查看create_default_context()
的代码表明,在这种情况下,可能禁用了证书检查,或者至少是可选的。
我有相同的错误消息(在Windows上),并通过以下方法解决了该问题:
import aiohttp
import ssl
client = aiohttp.ClientSession()
client.post(
'https://some.foo/bar/',
json={"foo": "bar"},
ssl=ssl.create_default_context(purpose=ssl.Purpose.CLIENT_AUTH))
这是使用request()的ssl
参数来设置与默认值不同的SSL上下文。默认值为ssl.create_default_context()。
问题是ssl.create_default_context()
的默认值为:
ssl.create_default_context(purpose=Purpose.SERVER_AUTH, cafile=None, capath=None, cadata=None)
在客户端上验证服务器证书时,Purpose.SERVER_AUTH
似乎不起作用。验证为客户端时,请使用Purpose.CLIENT_AUTH
。
答案 2 :(得分:0)
在具有过期CA根证书的旧Linux服务器上,我遇到了同样的问题,并且在SSLContext
中加载certifi CA证书包解决了该问题。
import aiohttp
import ssl
import certifi
ssl_context = ssl.create_default_context(cafile=certifi.where())
async with aiohttp.ClientSession() as session:
async with session.get('https://some.foo/bar/', ssl=ssl_context) as response:
print(await response.text())
答案 3 :(得分:0)
这对我有用:
if sys.version_info[0] == 3 and sys.version_info[1] >= 8 and sys.platform.startswith('win'):
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())