python - 带有 ssl 客户端证书的 aiohttp

标签 python ssl python-asyncio aiohttp

我正在尝试使用 asyncio 和 aiohttp 实现异步客户端,我有 API 凭据和 mTLS 证书来连接到某些服务的端点。但是当我打电话时它会挂起(直到超时)并给出<ClientResponse(https://<some endpoint>:8443/login) [504 Gateway Time-out]>实现相同但不异步(带有请求)工作得很好(在请求中提供带有 certs= 的证书)。
AFAIU,问题出在 ssl 上下文区域的某个地方……但我找不到……

class Test:
     def __init__(self, url: str):
        self.url = url
        self.api_creds = {"api_key": os.getenv("API_KEY"), "api_secret": os.getenv("API_SECRET")}
        self.headers = {"Content-Type": "application/json;charset=utf-8", "Content-Length": "20000"}   

     async def _post(self, path, payload):
        url = self.url + path
        sslcontext = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
        sslcontext.load_cert_chain(certfile='Path to mtls.crt', keyfile='Path .key')
        async with aiohttp.ClientSession(headers=headers) as session:
            try:
                response = await session.post(url, data=payload, ssl=sslcontext)
            except (aiohttp.ClientConnectorSSLError, aiohttp.ClientConnectorCertificateError) as e:
                logger.error(str(e))
        return response

    async def login(self):
        response = await self._post('/login', self.api_creds)
        print(response)
    

async def main():
  t = Test("https://EP url")
  await t.login()

loop = asyncio.get_event_loop()
loop.run_until_complete(main())
输出:
DEBUG asyncio : Using selector: KqueueSelector
DEBUG asyncio : Get address info <EP>:8443, type=<SocketKind.SOCK_STREAM: 1>, flags=<AddressInfo.AI_ADDRCONFIG: 1024>
DEBUG asyncio : Getting address info <EP>:8443, type=<SocketKind.SOCK_STREAM: 1>, flags=<AddressInfo.AI_ADDRCONFIG: 1024> took 47.029ms: [(<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_STREAM: 1>, 6, '', ('<IP>', 8443)), (<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_STREAM: 1>, 6, '', ('<IP>', 8443)), (<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_STREAM: 1>, 6, '', ('<IP>', 8443))]
DEBUG asyncio : <asyncio.sslproto.SSLProtocol object at 0x102e2ab20> starts SSL handshake
DEBUG asyncio : <asyncio.sslproto.SSLProtocol object at 0x102e2ab20>: SSL handshake took 188.5 ms
DEBUG asyncio : <asyncio.TransportSocket fd=9, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('192.168.86.20', 53514), raddr=('<IP>', 8443)> connected to <IP>:8443: (<asyncio.sslproto._SSLProtocolTransport object at 0x102f53be0>, <aiohttp.client_proto.ResponseHandler object at 0x102eebb80>)
<ClientResponse(https://EP:8443/login) [504 Gateway Time-out]>

最佳答案

您可以使用 ssl 默认上下文:

sslcontext = ssl.create_default_context(purpose=ssl.Purpose.CLIENT_AUTH)
sslcontext.load_cert_chain(certfile=cert_path, keyfile=key_path)
tcpconn = aiohttp.TCPConnector(ssl_context=sslcontext)
async with aiohttp.ClientSession(
        connector=tcpconn,
        headers={"Accept": "application/json"},
) as client:
  client.post(url, data=payload)

关于python - 带有 ssl 客户端证书的 aiohttp,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69816038/

相关文章:

python - Django REST Framework 嵌套序列化器 FK 创建

python - 遍历文件中的行会产生错误的行数

ssl - 带隧道的扭曲 Ratchet

java - 尝试从远程 SSL 地址下载和设置证书以进行 WebSocket 连接,但出现 "Signature does not match"异常

javascript - 带有 SSL 的 stomp+ActiveMQ

python - 如何使用 asyncio 在单独的线程上通知 RxPY 观察者?

python - 当我从 python 中的文本文件加载数据时出错

python - python tkinter 中的菜单 : save file to a new directory

python - 设置模拟 asyncio.coroutine 的返回值

python - 用asyncio转换一个简单的多线程程序