Como desabilito a verificação do certificado de segurança nas solicitações do Python

230

estou usando

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

mas recebo um request.exceptions.SSLError. O site tem um certificado expirado, mas não estou enviando dados confidenciais, portanto, isso não importa para mim. Imagino que exista um argumento como 'verifiy = False' que eu possa usar, mas não consigo encontrá-lo.

Paul Draper
fonte

Respostas:

411

A partir da documentação :

requeststambém pode ignorar a verificação do certificado SSL se você definir verifycomo Falso.

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

Se você estiver usando um módulo de terceiros e quiser desativar as verificações, aqui está um gerenciador de contexto que aplica os patches requestse os modifica para que verify=Falseseja o padrão e suprima o aviso.

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

Veja como você o usa:

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

Observe que esse código fecha todos os adaptadores abertos que trataram de uma solicitação corrigida depois que você saiu do gerenciador de contexto. Isso ocorre porque as solicitações mantêm um pool de conexões por sessão e a validação do certificado ocorre apenas uma vez por conexão, para que coisas inesperadas como essa ocorram:

>>> 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]>
Liquidificador
fonte
6
Obrigado, isso funciona se você tiver poucas chamadas de solicitações dentro do seu próprio código, mas imagine que eu quero desabilitar isso em uma terceira biblioteca parcialmente que usa solicitações ... seria impossível corrigir a lib de terceiros assim.
18713
7
@sorin: Basta patch de macaco requestse tem como verifypadrão False.
Blender
2
Como suprimir a grande mensagem de aviso desagradável que ainda é impressa?
Michael Michael
27
@ requests.packages.urllib3.disable_warnings()
Michael
8
@ Michael: ou para evitar esconder todas as advertências: from urllib3.exceptions import InsecureRequestWarningentãorequests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
Sébastien Deprez
96

Use requests.packages.urllib3.disable_warnings()e verify=Falseem requestsmétodos.

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)
efrenfuentes
fonte
11
Sua resposta é útil quando você deseja se livrar de avisos como "Solicitação de HTTPS não verificada está sendo feita". Mas verify=Falsedeve estar presente de qualquer maneira. Tnx.
Lufa 27/01
17
E para evitar esconder todas as advertências: from urllib3.exceptions import InsecureRequestWarningentãorequests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
Sébastien Deprez
Para aqueles que não podem desativar os avisos, você pode tentar requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning). Isso funciona porque garante que urllib3.exceptions.InsecureRequestWarningé exatamente o usado por requests.
AnnieFromTaiwan
32

Para adicionar à resposta do Blender , você pode desativar o SSL para todas as solicitações usandoSession.verify = False

import requests

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

Observe que urllib3 , (que o Requests usa), desencoraja fortemente a realização de solicitações HTTPS não verificadas e gera uma InsecureRequestWarning.

Stevoisiak
fonte
11

Também pode ser feito a partir da variável de ambiente:

export CURL_CA_BUNDLE=""
Stan Gabenov
fonte
1
Isso me dá: "OSError: Não foi possível encontrar um pacote de certificados TLS CA adequado, caminho inválido:" ". Estou usando a solicitação 2.22.0
chaim
ouexport REQUESTS_CA_BUNDLE='your-ca.pem'
weaming 28/11/19
1
Esta parece ser a melhor resposta caso você precise usar uma biblioteca que não pode editar
user989762
Baseado em CURL_CA_BUNDLE , os.environ['REQUESTS_CA_BUNDLE'] = 'FiddlerRootCertificate_Base64_Encoded_X.509.cer.pem' # your-ca.pemfunciona para o Python 3.8.3 ao usar o google-cloud-bigquery 1.24.0 e o BigQuery Client Lib para Python
samm
8

Se você deseja enviar exatamente uma solicitação de postagem com a opção check = False, a maneira mais rápida é usar este código:

import requests

requests.api.request('post', url, data={'bar':'baz'}, json=None, verify=False)
Ruslan Khyurri
fonte
O bandido não ficará feliz quando você desabilitar verificar = Falso. Vejo: docs.openstack.org/bandit/latest/plugins/…
kRazzy R
Olá, Tenho uma solicitação que me fornece a resposta da solicitação de postagem no Postman desativando a 'Verificação de certificado SSL' na opção de configuração. Mas, se eu receber o código de solicitação python fornecido pelo Postman, receberei o erro "Rotinas SSL '', 'tls_process_server_certificate', 'certificado verificação falhou" e adicionar o' confirm = False 'não ajuda neste caso. Existe alguma solução para obter a resposta do Postman no script de solicitação python?
Taha Hamedani