Come disabilitare il controllo del certificato di sicurezza nelle richieste Python


230

sto usando

import requests
requests.post(url='https://foo.com', data={'bar':'baz'})

ma ottengo un request.exceptions.SSLError. Il sito Web ha un certificato scaduto, ma non invio dati sensibili, quindi non mi interessa. Immagino che ci sia un argomento come 'verifiy = False' che potrei usare, ma non riesco a trovarlo.

Risposte:


411

Dalla documentazione :

requestspuò anche ignorare la verifica del certificato SSL se impostato verifysu False.

>>> requests.get('https://kennethreitz.com', verify=False)
<Response [200]>

Se si utilizza un modulo di terze parti e si desidera disabilitare i controlli, ecco un gestore di contesto che corregge le patch requestse lo modifica in modo che verify=Falsesia quello predefinito e sopprime l'avviso.

import warnings
import contextlib

import requests
from urllib3.exceptions import InsecureRequestWarning


old_merge_environment_settings = requests.Session.merge_environment_settings

@contextlib.contextmanager
def no_ssl_verification():
    opened_adapters = set()

    def merge_environment_settings(self, url, proxies, stream, verify, cert):
        # Verification happens only once per connection so we need to close
        # all the opened adapters once we're done. Otherwise, the effects of
        # verify=False persist beyond the end of this context manager.
        opened_adapters.add(self.get_adapter(url))

        settings = old_merge_environment_settings(self, url, proxies, stream, verify, cert)
        settings['verify'] = False

        return settings

    requests.Session.merge_environment_settings = merge_environment_settings

    try:
        with warnings.catch_warnings():
            warnings.simplefilter('ignore', InsecureRequestWarning)
            yield
    finally:
        requests.Session.merge_environment_settings = old_merge_environment_settings

        for adapter in opened_adapters:
            try:
                adapter.close()
            except:
                pass

Ecco come lo usi:

with no_ssl_verification():
    requests.get('https://wrong.host.badssl.com/')
    print('It works')

    requests.get('https://wrong.host.badssl.com/', verify=True)
    print('Even if you try to force it to')

requests.get('https://wrong.host.badssl.com/', verify=False)
print('It resets back')

session = requests.Session()
session.verify = True

with no_ssl_verification():
    session.get('https://wrong.host.badssl.com/', verify=True)
    print('Works even here')

try:
    requests.get('https://wrong.host.badssl.com/')
except requests.exceptions.SSLError:
    print('It breaks')

try:
    session.get('https://wrong.host.badssl.com/')
except requests.exceptions.SSLError:
    print('It breaks here again')

Si noti che questo codice chiude tutti gli adattatori aperti che hanno gestito una richiesta patchata una volta usciti dal gestore del contesto. Questo perché le richieste mantengono un pool di connessioni per sessione e la convalida del certificato avviene solo una volta per connessione, quindi accadranno cose inaspettate come questa:

>>> import requests
>>> session = requests.Session()
>>> session.get('https://wrong.host.badssl.com/', verify=False)
/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning)
<Response [200]>
>>> session.get('https://wrong.host.badssl.com/', verify=True)
/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning)
<Response [200]>

6
Grazie, questo funziona se hai poche richieste di chiamate all'interno del tuo codice, ma immagina che voglio disabilitarlo in una libreria parzialmente terza che utilizza le richieste, ... sarebbe impossibile correggere la lib di terze parti in questo modo.
Sorin,

7
@sorin: solo patch di scimmia requestse hanno l' verifyimpostazione predefinita False.
Blender il

2
Come posso sopprimere il grosso e spiacevole messaggio di avviso che viene ancora stampato?
Michael,

27
@Michael per rispondere alla mia domanda:requests.packages.urllib3.disable_warnings()
Michael

8
@Michael: o per evitare di nascondere tutti gli avvertimenti: from urllib3.exceptions import InsecureRequestWarningallorarequests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
Sébastien Deprez,

96

Utilizzare requests.packages.urllib3.disable_warnings()e verify=Falsesu requestsmetodi.

import requests
from urllib3.exceptions import InsecureRequestWarning

# Suppress only the single warning from urllib3 needed.
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)

# Set `verify=False` on `requests.post`.
requests.post(url='https://example.com', data={'bar':'baz'}, verify=False)

11
La tua risposta è utile quando vuoi sbarazzarti di Avvisi come "La richiesta HTTPS non verificata è in corso". Ma verify=Falsedeve essere presente comunque. Tnx.
Lufa,

17
E per evitare di nascondere tutti gli avvertimenti: from urllib3.exceptions import InsecureRequestWarningallorarequests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
Sébastien Deprez il

Per coloro che non possono disabilitare gli avvisi, puoi provare requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning). Questo funziona perché garantisce che urllib3.exceptions.InsecureRequestWarningsia quello esatto utilizzato da requests.
AnnieFromTaiwan,

32

Per aggiungere alla risposta di Blender , puoi disabilitare SSL per tutte le richieste usandoSession.verify = False

import requests

session = requests.Session()
session.verify = False
session.post(url='https://foo.com', data={'bar':'baz'})

Si noti che urllib3(che utilizza Requests), scoraggia fortemente l' inoltro di richieste HTTPS non verificate e genererà un InsecureRequestWarning.


11

Inoltre può essere fatto dalla variabile d'ambiente:

export CURL_CA_BUNDLE=""

1
Questo mi dà: "OSError: Impossibile trovare un pacchetto certificato TLS CA adatto, percorso non valido:" ". Sto usando la richiesta 2.22.0
chaim

oppureexport REQUESTS_CA_BUNDLE='your-ca.pem'
weaming,

1
Questa sembra essere la risposta migliore nel caso in cui sia necessario utilizzare una libreria che non è possibile modificare
user989762,

Basato su CURL_CA_BUNDLE , os.environ['REQUESTS_CA_BUNDLE'] = 'FiddlerRootCertificate_Base64_Encoded_X.509.cer.pem' # your-ca.pemfunziona con Python 3.8.3 quando si utilizza google-cloud-bigquery 1.24.0 e BigQuery Client Lib per Python
sabato

8

Se si desidera inviare esattamente la richiesta di post con l'opzione verifica = False, il modo più rapido è utilizzare questo codice:

import requests

requests.api.request('post', url, data={'bar':'baz'}, json=None, verify=False)

Bandit non sarà contento quando disabilitiify = False. Vedi: docs.openstack.org/bandit/latest/plugins/…
kRazzy R

Salve, ho una richiesta che mi dà la risposta della richiesta post nel Postman disabilitando la "verifica del certificato SSL" nell'opzione di impostazione. Ma, se ottengo il codice di richiesta Python fornito dal Postman, riceverò l'errore "Routine SSL", "tls_process_server_certificate", "verifica del certificato non riuscita" e l'aggiunta dell'errore "verifica = Falso" non aiuta in questo caso, è esiste qualche soluzione per ottenere la risposta del postino nello script di richiesta python?
Taha Hamedani,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.