Korzystam z żądań, aby połączyć się z interfejsem API RESTful. Serwer, z którym chciałbym skorzystać, korzysta z protokołu ssl z certyfikatem samokopiującym.
cafile = "gateway.pem"
r = requests.get(request, auth=("admin", "password"), verify=cafile)
problem polega na tym, że otrzymuję SSLError nazwy hostaniedopasowanie. powinien istnieć sposób na wyłączenie sprawdzania nazwy hosta bez wyłączania sprawdzania poprawności certyfikatu, tak jak w wielu implementacjach Java, ale nie mogę znaleźć sposobu na wykonanie tego w żądaniach w Pythonie.
Ślad stosu:
Traceback (most recent call last):
File "<pyshell#43>", line 1, in <module>
r = requests.get(request, auth=("admin", "password"), verify="gateway.pem")
File "C:Python27libsite-packagesrequests-2.0.0-py2.7.eggrequestsapi.py", line 55, in get
return request("get", url, **kwargs)
File "C:Python27libsite-packagesrequests-2.0.0-py2.7.eggrequestsapi.py", line 44, in request
return session.request(method=method, url=url, **kwargs)
File "C:Python27libsite-packagesrequests-2.0.0-py2.7.eggrequestssessions.py", line 357, in request
resp = self.send(prep, **send_kwargs)
File "C:Python27libsite-packagesrequests-2.0.0-py2.7.eggrequestssessions.py", line 460, in send
r = adapter.send(request, **kwargs)
File "C:Python27libsite-packagesrequests-2.0.0-py2.7.eggrequestsadapters.py", line 358, in send
raise SSLError(e)
SSLError: hostname "10.76.92.70" doesn"t match u"lital.com"
Jak to zrobić?
Odpowiedzi:
8 dla odpowiedzi № 1Żądania nie pozwalają na to bezpośrednio, jednak można zapewnić niestandardowy adapter transportu, który korzysta z funkcji urządzenia bazowego urllib3
. Korzystanie z adapterów transportowych jest opisane w dokumentacji wniosków.
Ten kod nie jest testowany, ale powinien działać.
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.poolmanager import PoolManager
# Never check any hostnames
class HostNameIgnoringAdapter(HTTPAdapter):
def init_poolmanager(self, connections, maxsize, block=False):
self.poolmanager = PoolManager(num_pools=connections,
maxsize=maxsize,
block=block,
assert_hostname=False)
# Check a custom hostname
class CustomHostNameCheckingAdapter(HTTPAdapter):
def cert_verify(self, conn, url, verify, cert):
# implement me
host = custom_function_mapping_url_to_hostname(url)
conn.assert_hostname = host
return super(CustomHostNameCheckingAdapter,
self).cert_verify(conn, url, verify, cert)
Szczegółowo assert_hostname
param działa w następujący sposób: Gdyby None
użyj nazwy hosta z adresu URL, jeśli False
pomiń sprawdzanie nazwy hosta, jeśli ciąg niestandardowy sprawdza poprawność względem tego ciągu.
4 dla odpowiedzi nr 2
Jestem trochę spóźniony na przyjęcie, ale requests_toolbelt
wygląda na to, że może pomóc, jeśli zainstalujesz wersję 0.7.0 lub nowszą (moje Ubuntu 16.04 ma tylko 0.6.0): https://toolbelt.readthedocs.io/en/latest/adapters.html#hostheaderssladapter
Z linku:
Example usage:
>>> s.mount("https://", HostHeaderSSLAdapter())
>>> s.get("https://93.184.216.34", headers={"Host": "example.org"})
1 dla odpowiedzi nr 3
Czy zajrzałeś do SSLContext.check_hostname
parametr? Powinieneś być w stanie ustawić go na False i nie powinien sprawdzać nazwy hosta:
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = True
context.load_default_certs()
Jedynym ograniczeniem jest to, że działa to tylko w Pythonie 3.4 i nowszych.
Odniesienie: https://docs.python.org/3/library/ssl.html#ssl.SSLContext.check_hostname
-2 dla odpowiedzi № 4
http://docs.python-requests.org/en/latest/user/advanced/#ssl-cert-verification
verify
słowo kluczowe jest flagą, a nie do dostarczania pliku certyfikatu. Podałeś tam niepisany ciąg, który rozwiązuje True
w kontekście logicznym.
Posługiwać się cert=
słowo kluczowe, aby podać ścieżkę do plików certyfikatu lub wyłączyć weryfikację za pomocą verify=False
.
EDYTOWAĆ: chociaż dokumentacja mówi, że można przekazać ścieżkę urzędu certyfikacji verify=
, ale nie ma przykładów. Byłoby pomocne zobaczyć cały otrzymywany ślad.
-3 dla odpowiedzi № 5
Jeśli jest to tylko do testowania, po prostu dodaj wpis w / etc / hosts do swojego lokalnego systemu (zakładając, że masz dostęp).