SSLErrorをスローするPythonリクエスト


348

CAS、jspringのセキュリティチェック、リダイレクトなどを含む簡単なスクリプトを作成しています。KennethReitzのpythonリクエストを使用したいのは、これがすばらしい作品だからです。ただし、CASはSSL経由で検証される必要があるため、最初にそのステップを通過する必要があります。Pythonリクエストで何が必要なのかわかりませんか?このSSL証明書はどこにあるはずですか?

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

コード情報をもっと共有できますか?足りないステップがあるようです。
TankorSmash

5
支援が必要なソフトウェアのバージョンについては常に言及する必要があります。
Piotr Dobrogost

私はpython 3.5 tornado 4.4を使用しているときにこの問題が発生しました。HTTPRequestはvalidate_cert = Trueを設定するため、Falseに設定して対処できます
pan7an

回答:


460

発生している問題は、信頼されていないSSL証明書が原因です。

前のコメントで述べた@dirkのように、最も速い修正は設定verify=Falseです:

requests.get('https://example.com', verify=False)

これにより証明書が検証されないことに注意してください。これにより、アプリケーションが中間者攻撃などのセキュリティリスクにさらされます。

もちろん、判決を適用します。コメントで述べたように、これ迅速な/使い捨てのアプリケーション/スクリプトでは許容できるかもしれませんが、実際には本番ソフトウェアに移動すべきではありません

特定のコンテキストで証明書のチェックをスキップするだけでは受け入れられない場合は、次のオプションを検討してください。最善のオプションは、verifyパラメータをパスの文字列に設定することです.pem、証明書ファイルのことです(これは、何らかの安全な方法で取得する必要があります)手段)。

そのため、バージョン2.0以降、verifyパラメータは次の値とそれぞれのセマンティクスを受け入れます。

  • True:証明書をライブラリ自体の信頼できる認証局に対して検証します(注:リクエストから抽出されたRCの信頼データベースであるCertifiライブラリを介して、どのルート証明書リクエストが使用するかを確認できます:Certifi-Trust Database for Humans)。
  • False:証明書の検証を完全にバイパスしますます。
  • 証明書の検証に使用するリクエストのCA_BUNDLEファイルへのパス。

ソース: リクエスト-SSL証明書の検証

またcert、同じリンクのパラメーターも確認してください。


1
はい、ubuntuでdotCloudを使用したときに、同じ「証明書の検証に失敗しました」が出ました。「/usr/local/lib/python2.6/dist-packages/dotcloud/client/client.py」の「requests.session(headers = headers、hooks = hooks、verify = False)」を変更した後、機能しました。
diyism 2013

2
これは正しいとマークされていませんが、(以下の回答とは対照的に)機能することを確認できます。
khalid13 2013

40
@ khalid13:斧は頭痛薬として機能します(頭なし-頭痛なし)。それをそのように使用することが良い考えであるという意味ではありません。verify=FalseホストのSSL証明書チェックを無効にします。
jfs

24
@JFSebastian正直なところ、それはあなたが何をしているかに依存します。私のクイック/使い捨てアプリケーションでは、それで十分でした。
khalid13 2013

5
そのような変更を行う@diyismは非常に危険に聞こえます...
binki

111

SSL検証に関するリクエストドキュメントから:

Webブラウザーと同様に、要求はHTTPS要求のSSL証明書を検証できます。ホストのSSL証明書を確認するには、verify引数を使用できます。

>>> requests.get('https://kennethreitz.com', verify=True)

SSL証明書を検証したくない場合は、 verify=False


4
まあ、verify = Trueを追加しましたが、それでもまったく同じエラーが発生しました。変化なし。他に必要なものがありますが、それが何であるかはわかりません。
TedBurrows、2012年

私は今、SSLマッドネスに降り立っていると思います。これを私の最初のget ... url(headers = headers、cert = '/ etc / pki / tls / cert.pem'、verify = True、config = my_config)に追加したので、今、このエラーが発生しています。requests.exceptions.SSLError:[Errno 336265225] _ssl.c:351:error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM libこれが何を意味するのかわかりません。
TedBurrows、2012年

14
証明書を検証したくない場合はverify = Falseを設定し、自己署名証明書がある場合はiow
Dirk

16
自己署名証明書がある場合は、それをダウンロードして、ファイル名を確認します。verify = Falseを設定するための言い訳は一切ありません。verify = '/ path / to / cert.pem'
Matthias Urlichs 2013年

14
申し訳ありませんが、リクエストは「ウェブブラウザのように」HTTPSリクエストを処理しないため、この回答に反対票を投じる必要がありました。完全なSSL信頼チェーン(中間証明書を含む)がサーバーで宣言されておらず、追加の証明書のダウンロードが必要な場合は、上記のSSL検証エラーが表示されます。Webブラウザーは追加のダウンロードを実行し、証明書エラーにフラグを立てません。これは、Webブラウザとリクエストが異なる1つの方法です。他にもあります。リクエストはいくつかの検証を行いますが、ブラウザほど良くありません。
Louis Cremen 2015年

53

使用するCAファイルの名前は、次を介して渡すことができますverify

cafile = 'cacert.pem' # http://curl.haxx.se/ca/cacert.pem
r = requests.get(url, verify=cafile)

あなたが使用している場合はverify=True、その後requests、サーバー証明書に署名したCAを持っていない可能性があり、独自のCAのセットを使用しています。


12
@ 9emE0iL18gxCqLT:すべてのシステムが指定されたパスを使用すると思いますか?requestsディストリビューション用にパッケージ化できます。python -mrequests.certsそれを指す場所を見つけるために実行します。
jfs

3
Pythonリクエストのcacertバンドルが古い場合、どうすれば更新できますか?
CMCDragonkai 2015

5
あなたはcacert.pemカールからそれを使うべきではありません。多くの失効した証明書が含まれています。Certifi(リクエストで使用)を確認してください:certifi.io
Kenneth Reitz

3
@KennethReitz:1- OPで要求の使用が失敗する(それ以外の場合は問題はありませんでした)2- cacert.pemはMozillaから(cURLによって)抽出されたCA証明書です -これは単なる例です(一般的なWebで使用されているCAリストの場合) -ブラウザは例として使用できませんが、何ができるかわかりません)- デフォルトのリストが失敗した場合に独自のCAファイルを渡すことができるという回答の要点。
jfs

これを行うと同時にクライアント証明書を使用できますか?これで問題が発生しています。
user1156544

42

$ pip install -U requests[security]

  • Python 2.7.6 @ Ubuntu 14.04.4 LTSでテスト済み
  • Python 2.7.5 @ MacOSX 10.9.5(Mavericks)でテスト済み

この質問が開かれたとき(2012-05)、リクエストのバージョンは0.13.1でした。バージョン2.4.1(2014-09)では、「セキュリティ」の追加機能が導入され、certifi可能な場合はパッケージを使用しています。

今(2016から09)主なバージョンが良い動作する、2.11.1ですなし verify=False。追加でrequests.get(url, verify=False)インストールされている場合、を使用する必要はありませんrequests[security]


7
pip install -U requests[security] --no-cache2回固定 pip install certifi==2015.04.28
Aamir Abro

@alanjds一部のssl証明書を信頼するようにpythonを構成するか、ソースコードを編集せずに環境内でグローバルに証明書の検証を無効にする場合はどうなりますか?たとえば、既存のPythonユーティリティ(AWS CLIなど)をダウンロードし、証明書を信頼するか、それらのツールの証明書検証を無視する場合はどうすればよいですか?
Howiecamp 2017年

あなたはJF-セバスチャンの答えを経由して行くことができる@Howiecampはその後、私は推測する:stackoverflow.com/a/12865159/798575を
alanjds

@alanjdsしかし、彼の答えは、私がコードを書いていること、および/またはコードにアクセスできることを前提としていますか?これを環境レベルで実装したいと考えています。
Howiecamp 2017年

3
pip install --upgrade pip他のエラーを回避するために、リクエストセキュリティパッケージをインストールする前に行う
Vincent Claes

40

aws boto3を使用しているときに同じ問題が発生し、ssl証明書が失敗したことを確認しました。boto3コードを確認するREQUESTS_CA_BUNDLEと、設定されていないことがわかったため、手動で設定して両方の問題を修正しました。

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

aws-cliの場合、REQUESTS_CA_BUNDLEを設定~/.bashrcするとこの問題が解決されると思います(私のaws-cliがそれなしで動作するため、テストされていません)。

REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt # ca-bundle.crt
export REQUESTS_CA_BUNDLE

2
これで問題が解決しました!MacでCharles Proxyを使用して、HTTPS APIへのJSON呼び出しを行うライブラリをデバッグしていました。Charless証明書を指定どおりにインストールし、キーチェーンに追加しましたが、Pythonは次のエラーで失敗しました:SSLError:( "bad handshake:Error([( 'SSL routines'、 'ssl3_get_server_certificate'、 'certificate verify failed')]、)" 、)これを修正するために、REQUESTS_CA_BUNDLEを追加し、チャールズの証明書をキーチェーンから.pemファイルとしてエクスポートするというアドバイスに従いました。今、それはうまくいきます!
mallyvai

おかげで、同じ問題がFiddlerを開いたときに発生しました
user565447

@ user565447私は今、これをFiddlerで動作させようとしています。REQUESTS_CA_BUNDLEをFiddlerの証明書に設定する必要がありますか?
Howiecamp 2017年

19

依存するライブラリrequestsがあり、検証パスを変更できない場合(などpyvmomi)には、cacert.pemバンドルされたリクエストを見つけてそこにCAを追加する必要があります。cacert.pem場所を見つける一般的な方法は次のとおりです。

ウィンドウズ

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

ところで。@ requests-devs、独自のcacertsをrequestにバンドルするのは本当に、本当に面倒です...特に、システムCAストアを最初に使用していないようで、これはどこにも文書化されていません。

更新

ライブラリを使用しており、ca-bundleの場所を制御できない状況では、ca-bundleの場所をホスト全体のca-bundleに明示的に設定することもできます。

REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-bundle.crt python -c "import requests; requests.get('https://somesite.com';)"

これの100倍:キーがverifyパスを変更できないこと。
ghukill

自己署名証明書を使用している場合はどうなりますか?その場合、CAはどうなりますか?
user1114

小さな更新-Python 3.6の場合、印刷コマンドの括弧が必要です
-python

15

私はgspreadを使用して同じ問題に直面し、これらのコマンドは私のために機能します:

sudo pip uninstall -y certifi
sudo pip install certifi==2015.04.28

これでうまくいきました。ありがとう:)
alex-mcleod

4
これには、古いバージョンのcertifiから潜在的に取り消された/信頼されていない証明書を再インストールするという欠点がありますが、これはお勧めできません。
dragon788

何らかの理由でpython 2.7の初期バージョンを使用せざるを得ない場合は、certifiのダウングレードが私にとって
有効な

15

警告を削除したい場合は、以下のコードを使用してください。

import urllib3

urllib3.disable_warnings()

verify=Falserequest.getpost方法


12

同様の問題を解決するための具体的なアプローチを見つけました。アイデアは、システムに保存されているcacertファイルを指しています他のsslベースのアプリケーションで使用されるます。

Debian(他のディストリビューションでも同じかどうかはわかりません)で、証明書ファイル(.pem)が次の場所に保存され/etc/ssl/certs/ています。これが私にとって機能するコードです。

import requests
verify='/etc/ssl/certs/cacert.org.pem'
response = requests.get('https://lists.cacert.org', verify=verify)

どのpemファイルを選択するかを推測するには、URLを参照して、証明書を生成した認証局(CA)を確認します。

編集:(3つ目のアプリを実行しているため)コードを編集できない場合は、pem証明書を直接/usr/local/lib/python2.7/dist-packages/requests/cacert.pem(たとえば、ファイルの最後にコピーして)に追加してみてください。


2
Pythonで使用されるCA_BUNDLEをデバッグするための関連記事
2013

/usr/local/lib/python2.7/dist-packages/requests/cacert.pemOSストアへのシンボリックリンクに置き換えるのはどうですか?
CMCDragonkai 2015

8

証明書を気にしない場合は、を使用してくださいverify=False

import requests

url = "Write your url here"

returnResponse = requests.get(url, verify=False)

7

何時間ものデバッグの後、私はこれを次のパッケージを使用してのみ機能させることができました:

requests[security]==2.7.0  # not 2.18.1
cryptography==1.9  # not 2.0

を使用して OpenSSL 1.0.2g 1 Mar 2016

これらのパッケージverify=Falseがないと動作しませんでした。

これが誰かの役に立つことを願っています。


5

同じ問題が発生しました。私はサーバーに中間証明書をインストールしていなかったことがわかりました(以下のように、証明書の下部に追加してください)。

https://www.digicert.com/ssl-support/pem-ssl-creation.htm

ca-certificatesパッケージがインストールされていることを確認します。

sudo apt-get install ca-certificates

時間を更新すると、これも解決する場合があります。

sudo apt-get install ntpdate
sudo ntpdate -u ntp.ubuntu.com

自己署名証明書を使用している場合は、おそらく手動でシステムに追加する必要があります。


これは、システム証明書を使用するようにDebian / Ubuntuによって変更されたapt-getを介したリクエストのインストールにのみ適用されることに注意してください。独自の慎重にキュレーションされたCAバンドルで適切な船をリクエストします:certifi.io
Kenneth Reitz

ルートCAで十分ではありませんか?なぜ中間体が必要なのですか?
ティミー2017年

5

リクエストの呼び出しがコードのどこかに埋め込まれていて、サーバー証明書をインストールしたくない場合は、デバッグ目的でのみ、リクエストをモンキーパッチすることができます。

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

本番環境では絶対に使用しないでください。


4

パーティーには遅すぎると思いますが、私のような仲間の放浪者のための修正を貼り付けたかったのです。したがって、Python 3.7.xでは次のことがうまくいきました

端末に次のように入力します

pip install --upgrade certifi      # hold your breath..

スクリプト/リクエストをもう一度実行してみて、機能するかどうかを確認します(まだ修正されていないと確信しています!)。うまくいかない場合は、ターミナルで次のコマンドを直接実行してみてください

open /Applications/Python\ 3.6/Install\ Certificates.command  # please replace 3.6 here with your suitable python version

3

私はHOURSの間この問題と戦った。

リクエストを更新してみました。次に、certifiを更新しました。私はcertifi.where()を確認するようにポイントしました(コードはデフォルトでこれを行っています)。何もうまくいきませんでした。

最後に、Pythonのバージョンをpython 2.7.11に更新しました。私はPython 2.7.5を使用していましたが、これには証明書の検証方法にいくつかの非互換性がありました。Python(および他のいくつかの依存関係)を更新すると、Pythonが機能し始めました。


OpenSSLを1.0.1以上のバージョンに更新した場合は、それが問題である可能性があります。以下の私の答えを参照してください。 stackoverflow.com/a/44543047/1413201
Tim Ludwinski 2017

Python 2.7.9から2.7.10に変更すると、これが修正されました。
クレイジースティック2017

3

これは@ rafael-almeidaの回答に似ていますが、リクエスト2.11以降では3つの値をverify取ることができず、実際には4つあることを指摘しておきます。

  • True:リクエストの内部の信頼されたCAに対して検証します。
  • False:証明書の検証を完全にバイパスます。(非推奨)
  • CA_BUNDLEファイルへのパス。リクエストはこれを使用してサーバーの証明書を検証します。
  • 公開証明書ファイルを含むディレクトリへのパス。リクエストはこれを使用してサーバーの証明書を検証します。

残りの私の答えは、#4についてです。証明書を含むディレクトリを使用して検証する方法:

必要な公開証明書を取得して、ディレクトリに配置します。

厳密に言えば、おそらく帯域外の方法で証明書を取得する必要がありますが、任意のブラウザを使用して証明書をダウンロードすることもできます。

サーバーが証明書チェーンを使用する場合は、チェーン内のすべての証明書を必ず取得してください。

リクエストのドキュメントによると、証明書を含むディレクトリは、最初に「rehash」ユーティリティ(openssl rehash)で処理する必要があります。

(これにはopenssl 1.1.1+が必要ですが、すべてのWindows openssl実装がrehashをサポートしているopenssl rehashわけではありません。動作しない場合は、https://github.com/ruby/openssl/blob/masterで rehash ruby​​スクリプトを実行してみてください。 /sample/c_rehash.rb、ただしこれは試していません。)

証明書を認識するリクエストを取得するのに問題がありましたが、openssl x509 -outform PEMコマンドを使用して証明書をBase64 .pem形式に変換した後、すべてが完全に機能しました。

また、遅延リハッシュを実行することもできます。

try:
    # As long as the certificates in the certs directory are in the OS's certificate store, `verify=True` is fine.
    return requests.get(url, auth=auth, verify=True)
except requests.exceptions.SSLError:
    subprocess.run(f"openssl rehash -compat -v my_certs_dir", shell=True, check=True)
    return requests.get(url, auth=auth, verify="my_certs_dir")

2

現在、このエラーの原因となっているリクエストモジュールに問題があり、v2.6.2からv2.12.4(ATOW)に存在しますhttps : //github.com/kennethreitz/requests/issues/2573

この問題の回避策は、次の行を追加することです。 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'


FWIW、それはまだrequest == 2.13.0で存在します。上記の回避策はまだそれを修正します。
タマシュSzelei

1

@Rafael Almeidaが述べたように、あなたが抱えている問題は、信頼できないSSL証明書が原因です。私の場合、SSL証明書はサーバーから信頼されていません。セキュリティを損なうことなくこれを回避するために、私は証明書ダウンロードしてサーバーにインストールしました(単に.crtファイルをダブルクリックしてから、証明書をインストール...)。


0

別のパッケージからリクエストが呼び出されている場合、オプションを追加することはできません。その場合、cacertバンドルに証明書を追加することは簡単な道です。たとえば、「StartCom Class 1 Primary Intermediate Server CA」を追加する必要があり、そのためにルート証明書をStartComClass1.pemにダウンロードしました。私のvirtualenvがcaldavという名前であることを考えると、私は証明書を追加しました:

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

それらのうちの1つで十分かもしれない、私はチェックしなかった


0

私は同様または同じ認証検証問題を抱えていました。OpenSSLのバージョンが1.0.2未満であり、その要求に依存しているため、強力な証明書を検証できないことがあります(こちらを参照)。CentOS 7は1.0.1eを使用しているようですが、問題があるようです。

CentOSでこの問題を回避する方法がわからなかったため、弱い1024ビットCA証明書を許可することにしました。

import certifi # This should be already installed as a dependency of 'requests'
requests.get("https://example.com", verify=certifi.old_where())

ArcGISによってインストールされたPython 2.7.10を使用していますが、certifiモジュールがインストールされていません。インストールされている要求モジュールはバージョン2.11.1です。
ルーカス

0

Python 3.4.0から3.4.6にアップグレードする必要がありました

pyenv virtualenv 3.4.6 myvenv
pyenv activate myvenv
pip install -r requirements.txt

0

私の場合、理由はかなり些細なものでした。

私は、SSL検証が数日前まで機能し、別のマシンで実際に機能していたことを知っていました。

次のステップは、検証が機能していたマシンと機能していないマシンの間で、証明書の内容とサイズを比較することでした。

これによりすぐに、「正しく機能していない」マシンの証明書は適切ではないと判断し、「適切な」証明書に置き換えると、すべて問題なく動作するようになりました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.