我最近从flask
+ requests
上移到了aiohttp
它的async http客户端.
在我的场景中,我需要调用API HTTPS
(使用自定义证书)并发送客户端证书.
对于第一部分(验证自定义证书),文档中的支持清晰明确,并且工作得很好.
另一方面,对于第二部分,我似乎无法找到一种简单的方法来附加自定义SSL客户端证书来授权客户端.
你们知道怎么做吗?非常感谢 !
编辑:我已经提交了一份PR,其中包含有关该主题的aiohttp文档的更新,并且已合并.
对于将来可能会遇到此问题的任何人
TL:DR
import ssl import aiohttp ssl_ctx = ssl.create_default_context(cafile='/path_to_client_root_ca') ssl_ctx.load_cert_chain('/path_to_client_public_key.pem', '/path_to_client_private_key.pem') conn = aiohttp.TCPConnector(ssl_context=ssl_ctx) session = aiohttp.ClientSession(connector=conn) # session will now send client certificates..
长的故事-我看它是如何实现的请求(整齐地记录了API 在这里),显然它的内部实现urllib3.
urllib3将cert
参数一直向下流入其HTTPSConnection对象,最终调用此函数:
... self.sock = ssl_wrap_socket( sock=conn, keyfile=self.key_file, certfile=self.cert_file, ssl_context=self.ssl_context, ) ...
这样做:
... if ca_certs or ca_cert_dir: try: context.load_verify_locations(ca_certs, ca_cert_dir) except IOError as e: # Platform-specific: Python 2.6, 2.7, 3.2 raise SSLError(e) # Py33 raises FileNotFoundError which subclasses OSError # These are not equivalent unless we check the errno attribute except OSError as e: # Platform-specific: Python 3.3 and beyond if e.errno == errno.ENOENT: raise SSLError(e) raise elif getattr(context, 'load_default_certs', None) is not None: # try to load OS default certs; works well on Windows (require Python3.4+) context.load_default_certs() if certfile: context.load_cert_chain(certfile, keyfile) if HAS_SNI: # Platform-specific: OpenSSL with enabled SNI return context.wrap_socket(sock, server_hostname=server_hostname) ...
这里有趣的调用是load_cert_chain
- 这意味着如果我们只创建一个ssl.SSLContext
(这是一个标准库接口)对象并load_cert_chain
使用我们的客户端证书调用,aiohttp的行为与requests\urllib3相同.
因此,虽然aiohttp的文档缺乏告诉您的内容,但它们确实指定您可以加载自己的文档ssl.SSLContext
.