2017-01-17 2 views
2

ich vor kurzem von flask + requests auf aiohttp und seine Asynchron-http-Client bewegt wird.aiohttp und clientseitige SSL-Zertifikate

In meinem Szenario muss ich eine API über HTTPS (mit benutzerdefinierten Zertifikaten) aufrufen UND ein clientseitiges Zertifikat mitschicken.

Für den ersten Teil (Validierung benutzerdefinierte Zertifikate), ist die Unterstützung klar clearly documented int the docs und es funktioniert gut.

Auf der anderen Seite, für den zweiten Teil kann ich nicht in der Lage sein, eine einfache Möglichkeit zu finden, ein benutzerdefiniertes SSL-clientseitige Zertifikat zu identifizieren, um den Client zu autorisieren.

Wissen Sie, wie man das macht? Danke vielmals !

Antwort

6

BEARBEITEN: Ich habe eine PR mit einem Update auf die Aiohttp Dokumentation bezüglich des Themas eingereicht, und es wurde zusammengeführt.

Für alle, die dieses Problem in Zukunft begegnen könnte ..

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.. 

Die lange Geschichte - ich habe sah, wie es in Anfragen implementiert ist (die fein säuberlich dokumentiert API here), und anscheinend ist es in urllib3 implementiert.

urllib3 rinnt den cert Parameter den ganzen Weg hinunter zu seinem HTTPSConnection Objekt, wo es schließlich diese Funktion aufruft:

... 
self.sock = ssl_wrap_socket(
    sock=conn, 
    keyfile=self.key_file, 
    certfile=self.cert_file, 
    ssl_context=self.ssl_context, 
) 
... 

die tut: hier

... 
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) 
... 

Der interessante Aufruf load_cert_chain ist - Dies bedeutet, dass, wenn wir einfach ein ssl.SSLContext Objekt erstellen und load_cert_chain mit unseren Client-Zertifikaten wie folgt aufrufen, aiohttp wird beh ave das gleiche wie Anfragen \ urllib3.

Also, aiohttp die Dokumentation fehlt Ihnen das sagen, sie angeben, dass Sie Ihre eigenen ssl.SSLContext laden können.