1. ホーム
  2. パイソン

[解決済み】urllibと「SSL: CERTIFICATE_VERIFY_FAILED」エラーの関係

2022-03-25 18:45:18

質問

以下のエラーが発生します。

Exception in thread Thread-3:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 810, in        __bootstrap_inner
self.run()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 763, in  run
self.__target(*self.__args, **self.__kwargs)
File "/Users/Matthew/Desktop/Skypebot 2.0/bot.py", line 271, in process
info = urllib2.urlopen(req).read()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 154, in urlopen
return opener.open(url, data, timeout)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 431, in open
response = self._open(req, data)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 449, in _open
'_open', req)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 409, in _call_chain
result = func(*args)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 1240, in https_open
context=self._context)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 1197, in do_open
raise URLError(err)
URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:581)>

このエラーを引き起こしているコードです。

if input.startswith("!web"):
    input = input.replace("!web ", "")      
    url = "https://domainsearch.p.mashape.com/index.php?name=" + input
    req = urllib2.Request(url, headers={ 'X-Mashape-Key': 'XXXXXXXXXXXXXXXXXXXX' })
    info = urllib2.urlopen(req).read()
    Message.Chat.SendMessage ("" + info)

使用しているAPIはHTTPSを使用する必要があります。どうすれば検証を回避できるのでしょうか?

解決方法は?

もし、あなたが ただ を使用すると、検証を回避することができます。 SSLContext . デフォルトでは、新しく作成されたコンテキストは CERT_NONE .

セクションに記載されているように、これには注意が必要です。 17.3.7.2.1

SSLContext のコンストラクタを直接呼び出す場合、CERT_NONE がデフォルトである。これは相手側を認証しないので、特にクライアントモードでは安全ではありません。したがって、クライアントモードでは、CERT_REQUIREDを使用することが強く推奨されます。

しかし、もし他の理由で今すぐ動作させたいだけなら、次のようにすることができます。 import ssl にも対応しています。

input = input.replace("!web ", "")      
url = "https://domainsearch.p.mashape.com/index.php?name=" + input
req = urllib2.Request(url, headers={ 'X-Mashape-Key': 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' })
gcontext = ssl.SSLContext()  # Only for gangstars
info = urllib2.urlopen(req, context=gcontext).read()
Message.Chat.SendMessage ("" + info)

これで問題は解決するはずですが、実際には何の問題も解決していません。 [SSL: CERTIFICATE_VERIFY_FAILED] なぜなら、今は証明書を検証していないからです!

上記の補足として、なぜこのような問題が発生するのかについて詳しく知りたい場合は、以下を参照してください。 PEP 476 .

この PEP は、Python の HTTP クライアントで X509 証明書の署名の検証、およびホスト名の検証をデフォルトで有効にすることを提案するもので、呼び出しごとにオプトアウトすることができます。この変更は Python 2.7, Python 3.4, Python 3.5 に適用される予定です。

上記の私のアドバイスと同じようなオプトアウトのアドバイスがあります。

import ssl

# This restores the same behavior as before.
context = ssl._create_unverified_context()
urllib.urlopen("https://no-valid-cert", context=context)

また 非推奨 オプションで モンキーパッチ Pythonではあまり見かけないものです。

import ssl

ssl._create_default_https_context = ssl._create_unverified_context

これは、コンテキストを作成するためのデフォルトの関数を、検証されていないコンテキストを作成するための関数でオーバーライドします。

PEPに記載されている通りですので、ご注意ください。

このガイダンスは、主に HTTPS 接続時の証明書検証をまだサポートしていないレガシー環境において、この PEP を実装した新しいバージョンの Python を採用したいシステム管理者を対象としています。例えば、管理者は Python の標準オペレーティング環境の sitecustomize.py に上記の monkeypatch を追加することでオプトアウトすることができます。 アプリケーションやライブラリは、この変更プロセスを広く行うべきではありません。 (システム管理者が制御するコンフィギュレーション設定に対応する場合を除く)。

なぜソフトウェアで証明書を検証しないことが悪いのかについての論文を読みたい場合 こちらでご覧いただけます。 !