requests bewusst wraps low-level-Sachen wie diese. Normalerweise ist die einzige Sache, die Sie tun möchten, ist zu stellen Sie sicher, dass die Zertifikate gültig sind. Das zu tun, nur pass verify=True. Wenn Sie möchten, verwenden Sie eine nicht-standard-cacert-bundle können Sie passieren, auch. Zum Beispiel:
Auch requests ist in Erster Linie ein Satz von Wrapper um andere libraries, meist urllib3 und die stdlib ist http.client (oder, für die 2.x, httplib) und ssl.
Manchmal, die Antwort ist einfach, um auf der unteren Ebene Objekte (z.B. resp.raw ist die urllib3.response.HTTPResponse), aber in vielen Fällen unmöglich.
- Und dies ist einer dieser Fälle. Die einzigen Objekte, die jemals in die APZ sind ein http.client.HTTPSConnection (oder ein urllib3.connectionpool.VerifiedHTTPSConnection, aber das ist nur eine Unterklasse der ehemaligen) und eine ssl.SSLSocket, und keiner von denen mehr existieren durch die Zeit, die die Anfrage zurückgibt. (Wie der name connectionpool andeutet, ist der HTTPSConnection Objekt gespeichert ist, in einem Schwimmbad, und wieder verwendet werden kann, sobald es fertig ist; die SSLSocket ist ein Mitglied der HTTPSConnection.)
So, müssen Sie zu patch Dinge, so dass Sie können kopieren Sie die Daten der Kette. Es kann so einfach wie diese:
Das ist ungetestet, also keine Garantie, die Sie benötigen, um den patch mehr als das.
Auch, vererben und überschreiben, wäre wahrscheinlich sauberer als monkeypatching (vor allem, da HTTPAdapter entwickelt wurde, um die Unterklassen).
Oder, noch besser, forking urllib3 und requests ändern, Ihre Gabel, und (wenn Sie denken, das ist legitim nützlich) die pull-Anforderungen upstream.
Sowieso, jetzt, von Ihrem code, können Sie dies tun:
resp.peercert
Dadurch erhalten Sie ein dict mit 'subject' und 'subjectAltName' Schlüssel zurückgegeben pyopenssl.WrappedSocket.getpeercert. Wenn Sie stattdessen möchten Sie weitere Informationen über das cert, versuchen Christophe Vandeplas Variante dieser Antwort, die Sie können, get ein OpenSSL.crypto.X509 Objekt. Wenn Sie möchten, um die gesamte peer-Zertifikat-Kette, siehe GoldenStake Antwort.
Natürlich können Sie auch weitergeben möchten alle notwendigen Informationen, um zu überprüfen, das cert, aber das ist sogar noch einfacher, da es bereits Pässe durch die Obere Ebene.
Wow, das ist sehr komplett. Vielen Dank! Ich werde daran arbeiten und sehen, wie es geht. Nochmals vielen Dank!
Danke, das hat wirklich geholfen. Leider, wenn der server verwendet Connection: close und schließt die Verbindung sofort, nachdem die Daten übertragen, ich würde noch nicht die "peercert". Ich hatte den patch requests.packages.urllib3.connection.HTTPSConnection.connect auch zuerst die ursprüngliche Funktion aufrufen und dann sofort den self.sock.getpeercert() und dann geben Sie sich die Kette.
Starten, abarnert Antwort ist sehr komplett. Während der Jagd die vorgeschlagene connection-close Thema Kalkran ich tatsächlich entdeckt, dass der peercert nicht enthalten ausführliche Informationen über das SSL-Zertifikat.
Ich grub tiefer in die Verbindung und socket-Informationen und extrahiert die self.sock.connection.get_peer_certificate() Funktion enthält Funktionen wie:
get_subject() für CN
get_notAfter() und get_notBefore() für Ablaufdaten
get_serial_number() und get_signature_algorithm() für crypto Verwandte technische details
...
Beachten Sie, dass diese nur zur Verfügung, wenn Sie pyopenssl auf Ihrem system installiert. Unter der Haube urllib3 verwendet pyopenssl wenn es verfügbar ist und der standard-Bibliothek ssl Modul anders. Die self.sock.connection - Attribut angezeigt, unten gibt es nur, wenn self.sock ist ein urllib3.contrib.pyopenssl.WrappedSocket, wenn es nicht eine ssl.SSLSocket. Sie können installieren pyopenssl mit pip install pyopenssl.
Werden Sie in der Lage, den Zugriff auf das Ergebnis leicht:
r = requests.get('https://yourdomain.tld', timeout=0.1)print('Expires on: {}'.format(r.peer_certificate.get_notAfter()))print(dir(r.peer_certificate))
Wenn, wie mir, die Sie ignorieren möchten SSL-Zertifikat-Warnungen fügen Sie einfach die folgenden in den Anfang der Datei und nicht von SSL überprüfen:
from requests.packages.urllib3.exceptions importInsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
r = requests.get('https://yourdomain.tld', timeout=0.1, verify=False)print(dir(r.peer_certificate))
Vielen Dank für die große Bereicherung für die Antwort! +1.
import requests
req = requests.get('https://httpbin.org')
pool = req.connection.poolmanager.connection_from_url('https://httpbin.org')
conn = pool.pool.get()# get() removes it from the pool, so put it back in
pool.pool.put(conn)print(conn.sock.getpeercert())
Dies funktioniert nur, wenn die Verbindung noch aktiv ist, ist nicht garantiert. Zum Beispiel, wenn die andere Seite sendet eine Connection: close. Oder wenn Sie geschickt haben andere Anforderungen (vor allem, wenn Sie mit diesem in einen async-oder Thread-Kontext). Oder wenn urllib3 fühlt sich einfach wie es ohne ersichtlichen Grund.
requests
bewusst wraps low-level-Sachen wie diese. Normalerweise ist die einzige Sache, die Sie tun möchten, ist zu stellen Sie sicher, dass die Zertifikate gültig sind. Das zu tun, nur passverify=True
. Wenn Sie möchten, verwenden Sie eine nicht-standard-cacert-bundle können Sie passieren, auch. Zum Beispiel:Auch
requests
ist in Erster Linie ein Satz von Wrapper um andere libraries, meisturllib3
und die stdlib isthttp.client
(oder, für die 2.x,httplib
) undssl
.Manchmal, die Antwort ist einfach, um auf der unteren Ebene Objekte (z.B.
resp.raw
ist dieurllib3.response.HTTPResponse
), aber in vielen Fällen unmöglich.- Und dies ist einer dieser Fälle. Die einzigen Objekte, die jemals in die APZ sind ein
http.client.HTTPSConnection
(oder einurllib3.connectionpool.VerifiedHTTPSConnection
, aber das ist nur eine Unterklasse der ehemaligen) und einessl.SSLSocket
, und keiner von denen mehr existieren durch die Zeit, die die Anfrage zurückgibt. (Wie der nameconnectionpool
andeutet, ist derHTTPSConnection
Objekt gespeichert ist, in einem Schwimmbad, und wieder verwendet werden kann, sobald es fertig ist; dieSSLSocket
ist ein Mitglied derHTTPSConnection
.)So, müssen Sie zu patch Dinge, so dass Sie können kopieren Sie die Daten der Kette. Es kann so einfach wie diese:
Das ist ungetestet, also keine Garantie, die Sie benötigen, um den patch mehr als das.
Auch, vererben und überschreiben, wäre wahrscheinlich sauberer als monkeypatching (vor allem, da
HTTPAdapter
entwickelt wurde, um die Unterklassen).Oder, noch besser, forking
urllib3
undrequests
ändern, Ihre Gabel, und (wenn Sie denken, das ist legitim nützlich) die pull-Anforderungen upstream.Sowieso, jetzt, von Ihrem code, können Sie dies tun:
Dadurch erhalten Sie ein dict mit
'subject'
und'subjectAltName'
Schlüssel zurückgegebenpyopenssl.WrappedSocket.getpeercert
. Wenn Sie stattdessen möchten Sie weitere Informationen über das cert, versuchen Christophe Vandeplas Variante dieser Antwort, die Sie können, get einOpenSSL.crypto.X509
Objekt. Wenn Sie möchten, um die gesamte peer-Zertifikat-Kette, siehe GoldenStake Antwort.Natürlich können Sie auch weitergeben möchten alle notwendigen Informationen, um zu überprüfen, das cert, aber das ist sogar noch einfacher, da es bereits Pässe durch die Obere Ebene.
Connection: close
und schließt die Verbindung sofort, nachdem die Daten übertragen, ich würde noch nicht die "peercert". Ich hatte den patchrequests.packages.urllib3.connection.HTTPSConnection.connect
auch zuerst die ursprüngliche Funktion aufrufen und dann sofort denself.sock.getpeercert()
und dann geben Sie sich die Kette.Starten, abarnert Antwort ist sehr komplett. Während der Jagd die vorgeschlagene
connection-close
Thema Kalkran ich tatsächlich entdeckt, dass derpeercert
nicht enthalten ausführliche Informationen über das SSL-Zertifikat.Ich grub tiefer in die Verbindung und socket-Informationen und extrahiert die
self.sock.connection.get_peer_certificate()
Funktion enthält Funktionen wie:get_subject()
für CNget_notAfter()
undget_notBefore()
für Ablaufdatenget_serial_number()
undget_signature_algorithm()
für crypto Verwandte technische detailsBeachten Sie, dass diese nur zur Verfügung, wenn Sie
pyopenssl
auf Ihrem system installiert. Unter der Haubeurllib3
verwendetpyopenssl
wenn es verfügbar ist und der standard-Bibliothekssl
Modul anders. Dieself.sock.connection
- Attribut angezeigt, unten gibt es nur, wennself.sock
ist einurllib3.contrib.pyopenssl.WrappedSocket
, wenn es nicht einessl.SSLSocket
. Sie können installierenpyopenssl
mitpip install pyopenssl
.Sobald dies erfolgt ist, der code wird:
Werden Sie in der Lage, den Zugriff auf das Ergebnis leicht:
Wenn, wie mir, die Sie ignorieren möchten SSL-Zertifikat-Warnungen fügen Sie einfach die folgenden in den Anfang der Datei und nicht von SSL überprüfen:
Diese, obwohl nicht ziemlich an allem arbeitet:
Connection: close
. Oder wenn Sie geschickt haben andere Anforderungen (vor allem, wenn Sie mit diesem in einen async-oder Thread-Kontext). Oder wennurllib3
fühlt sich einfach wie es ohne ersichtlichen Grund.Vielen Dank für alle genial Antworten.
Es hat mir geholfen, über Ingenieur eine Antwort auf diese Frage:
Wie hinzufügen eines benutzerdefinierten CA-Root-Zertifikat der CA Store verwendet Python in Windows?
UPDATE 2019-02-12
Stand-alone-snippet
Starten, abarnert Antwort ist sehr komplett
Aber ich möchte hinzufügen, dass in dem Fall Sie suchen für die peer-cert-Kette, würden Sie brauchen, um den patch wieder ein Stück code
nach, die Sie anrufen können es in einer sehr ähnlichen Art und Weise wie die akzeptierte Antwort
erhalten Sie
resp.peercertchain
enthält einetuple
vonOpenSSL.crypto.X509
Objekte