Pedidos em Python a atirar o SSLError
Traceback (most recent call last):
File "./test.py", line 24, in <module>
response = requests.get(url1, headers=headers)
File "build/bdist.linux-x86_64/egg/requests/api.py", line 52, in get
File "build/bdist.linux-x86_64/egg/requests/api.py", line 40, in request
File "build/bdist.linux-x86_64/egg/requests/sessions.py", line 209, in request
File "build/bdist.linux-x86_64/egg/requests/models.py", line 624, in send
File "build/bdist.linux-x86_64/egg/requests/models.py", line 300, in _build_response
File "build/bdist.linux-x86_64/egg/requests/models.py", line 611, in send
requests.exceptions.SSLError: [Errno 1] _ssl.c:503: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
19 answers
O problema que está a ter é causado por um certificado SSL Não fiável.
Tal como @dirk mencionou num comentário anterior, omais rápido está a definir verify=False
:
requests.get('https://example.com', verify=False)
Por favor, note que isto fará com que o certificado não seja verificado. Isto vai expor a sua aplicação a riscos de segurança, como ataques de homens no meio.
Claro, julgar. Tal como mencionado nos comentários, este pode ser aceitável para uma solução rápida/descartável. applications / scripts, but really should not go to production software .
Se ignorar a verificação do certificado não for aceitável no seu contexto particular, considere as seguintes opções, a sua melhor opção é definir o parâmetro verify
para um texto que é a localização do ficheiro .pem
do certificado (que deverá obter por algum tipo de meios seguros).
Assim, a partir da versão 2.0, o parâmetro verify
aceita os seguintes valores, com os respectivos valores semântica:
-
True
: faz com que o certificado seja validado pelas próprias autoridades de certificação de confiança da biblioteca (Nota: poderá ver quais os pedidos de certificados de raiz que usam através da Biblioteca Certifi, uma base de dados de confiança de RCs extraída de Pedidos: Certifici - Trust Database for Humans). -
False
: contorna a validação do certificado completamente. - localização de um ficheiro CA_ Bundle para os pedidos a usar para validar o certificado.
Fonte: pedidos-verificação do certificado SSL
Também dê uma olhada no parâmetro cert
no mesmo link.
A partir de Pedidos documentação relativa à verificação SSL:
Os pedidos podem verificar os certificados SSL para os pedidos HTTPS, tal como um navegador web. Para verificar o certificado SSL de uma máquina, poderá usar o argumento de verificação:
>>> requests.get('https://kennethreitz.com', verify=True)
Se não quiser verificar o seu certificado SSL, Faça verify=False
O nome do ficheiro AC a usar pode passar por verify
:
cafile = 'cacert.pem' # http://curl.haxx.se/ca/cacert.pem
r = requests.get(url, verify=cafile)
Se você usar verify=True
então requests
usa o seu próprio conjunto de AC que pode não ter AC que assinou o seu certificado de servidor.
$ pip install -U requests[security]
- testado em Python 2.7.6 @ Ubuntu 14. 04. 4 LTS
- testado em Python 2.7.5 @ MacOSX 10.9.5 (Mavericks)
certifi
pacote, se disponível.
Agora (2016-09) a versão principal é 2.11.1, que funciona bem sem verify=False
. Não é necessário utilizar requests.get(url, verify=False)
, Se instalado com requests[security]
extra.
Encontrei o mesmo problema e a verificação do certificado ssl falhou ao usar o código aws boto3, através da revisão do Código boto3, descobri que o REQUESTS_CA_BUNDLE
não está definido, por isso corrigi ambos os problemas ao configurá-lo manualmente:
from boto3.session import Session
import os
# debian
os.environ['REQUESTS_CA_BUNDLE'] = os.path.join(
'/etc/ssl/certs/',
'ca-certificates.crt')
# centos
# 'ca-bundle.crt')
Para o aws-cli, acho que a configuração do REQUESTS_ CA_BUNDLE em ~/.bashrc
irá corrigir este problema (não testado porque o meu aws-cli funciona sem ele).
REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt # ca-bundle.crt
export REQUESTS_CA_BUNDLE
Eu enfrento o mesmo problema usando o gspread e estes comandos funcionam para mim:
sudo pip uninstall -y certifi
sudo pip install certifi==2015.04.28
No caso de ter uma biblioteca que depende de requests
e de não poder modificar o caminho de verificação (como em pyvmomi
), então terá de encontrar o cacert.pem
empacotado com pedidos e adicionar o seu AC lá. Aqui está uma abordagem genérica para encontrar a localização cacert.pem
:
Janelas
C:\>python -c "import requests; print requests.certs.where()"
c:\Python27\lib\site-packages\requests-2.8.1-py2.7.egg\requests\cacert.pem
Linux
# (py2.7.5,requests 2.7.0, verify not enforced)
root@host:~/# python -c "import requests; print requests.certs.where()"
/usr/lib/python2.7/dist-packages/certifi/cacert.pem
# (py2.7.10, verify enforced)
root@host:~/# python -c "import requests; print requests.certs.where()"
/usr/local/lib/python2.7/dist-packages/requests/cacert.pem
[8] Btw. @requests-devs, juntar seus próprios cacetes com pedido é realmente, realmente irritante... especialmente o fato de que você não parece usar o system ca store primeiro, e isto não está documentado em lado nenhum.
Actualizar
Em situações, onde você estiver usando uma biblioteca e não tem nenhum controle sobre o ca-bundle de localização, você também pode definir explicitamente o ca-bundle local para ser seu anfitrião-grande ca-bundle:
REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-bundle.crt python -c "import requests; requests.get('https://somesite.com';)"
No Debian (Não tenho certeza se é o mesmo em outras distribuições) os arquivos de certificados (.pem) são armazenados em {[[1]} assim, este é o código que funciona para mim:
import requests
verify='/etc/ssl/certs/cacert.org.pem'
response = requests.get('https://lists.cacert.org', verify=verify)
Para adivinhar o que pem
ficheiro escolher, tenho de navegar pelo url e verificar qual a autoridade do certificado (AC) que gerou o certificado.
Editar: se não conseguir editar o código (porque está a correr uma terceira aplicação), poderá tentar adicionar o certificado pem
directamente em /usr/local/lib/python2.7/dist-packages/requests/cacert.pem
(por exemplo, copiá-lo para o fim do ficheiro).
Se quiser remover os avisos, use o código abaixo.
import urllib3
urllib3.disable_warnings()
E verify=False
com request.get
ou post
Método
Se não se preocupar com o certificado, basta usar verify=False
.
import requests
url = "Write your url here"
returnResponse = requests.get(url, verify=False)
Após horas de depuração só consegui que isto funcionasse usando os seguintes pacotes:
requests[security]==2.7.0 # not 2.18.1
cryptography==1.9 # not 2.0
Utilizar OpenSSL 1.0.2g 1 Mar 2016
Sem estes pacotes verify=False
não estava a funcionar.
Https://www.digicert.com/ssl-support/pem-ssl-creation.htm
Certifique-se que tem o pacote de certificados ca instalado:
sudo apt-get install ca-certificates
Actualizar o tempo também pode resolver isto:
sudo apt-get install ntpdate
sudo ntpdate -u ntp.ubuntu.com
Se estiver a usar um certificado assinado por si próprio, provavelmente terá de O adicionar ao seu sistema. manualmente.
Finalmente actualizei a minha versão do python para o python 2.7.11. Eu estava no Python 2.7.5, que tinha algumas incompatibilidades com a forma como os certificados são verificados. Uma vez que eu atualizei Python (e um punhado de outras dependências), ele começou a funcionar.
Existe actualmente um problema no módulo de pedidos que causa este erro, presente em v2. 6. 2 a v2. 12. 4 (ATOW): https://github.com/kennethreitz/requests/issues/2573
A solução para esta questão é adicionar a seguinte linha: requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS = 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS'
Se as chamadas de pedido estiverem enterradas algures no código e não quiser instalar o certificado do servidor, então, apenas para apenas para efeitos de depuração , é possível obter pedidos de monkeypatch:
import requests.api
import warnings
def requestspatch(method, url, **kwargs):
kwargs['verify'] = False
return _origcall(method, url, **kwargs)
_origcall = requests.api.request
requests.api.request = requestspatch
warnings.warn('Patched requests: SSL verification disabled!')
Nunca usar na produção!
Não é possível adicionar opções se os pedidos forem chamados de outro pacote. Nesse caso, adicionar certificados ao pacote cacert é o caminho reto, por exemplo, eu tive que adicionar "StartCom Classe 1 servidor intermediário primário CA", para o qual eu baixei o certificado de raiz para StartComClass1.pem. dado que o meu virtualenv se chama caldav, adicionei o certificado com:
cat StartComClass1.pem >> .virtualenvs/caldav/lib/python2.7/site-packages/pip/_vendor/requests/cacert.pem
cat temp/StartComClass1.pem >> .virtualenvs/caldav/lib/python2.7/site-packages/requests/cacert.pem
Um deles pode ser suficiente, Eu não verifiquei.
import certifi # This should be already installed as a dependency of 'requests'
requests.get("https://example.com", verify=certifi.old_where())
Tive de actualizar do Python 3.4.0 para 3.4.6
pyenv virtualenv 3.4.6 myvenv
pyenv activate myvenv
pip install -r requirements.txt