ブログ

Python で [SSL: CERTIFICATE_VERIFY_FAILED] になったときの対処法

症状

  • urllib.request.urlopen などの httpsアクセス結果が以下になってしまう

ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1076)

  • feedparser.parse の返り値を出力すると以下になってしまう
{'bozo': True, 'entries': [], 'feed': {}, 'headers': {}, 'bozo_exception': URLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1076)'))}

原因

  • OpenSSL使用時(httpsアクセス時)の証明書パスがおかしい

確認方法は以下。

python -c "import ssl;print(ssl.get_default_verify_paths())"

上記コマンドの結果が以下。

DefaultVerifyPaths(
cafile='C:\\Users\\(ユーザー名)\\anaconda3\\lib\\site-packages\\certifi\\cacert.pem', 
capath=None, 
openssl_cafile_env='SSL_CERT_FILE', 
openssl_cafile='C:\\Program Files\\Common Files\\SSL/cert.pem', 
openssl_capath_env='SSL_CERT_DIR', 
openssl_capath='C:\\Program Files\\Common Files\\SSL/certs'
)

openssl_cafile が C:\\Program Files\\Common Files\\SSL/cert.pem になっているが、そのパスには cert.pem が存在していなかった。

そして、openssl_cafile, openssl_capath は OpenSSL にハードコードされているらしく、それらを変更する方法を見つけることができなかった。

つまり、OpenSSL使用時に存在しない pem を使用しようとしていることが原因。

対処法

+ A. requests.get を使用する方法(クリックで展開)

requests.get を使用する方法

urllib.request.urlopen ではなく requests.get を使用する。

import requests
requests.get(https_url)

+ B. SSLContextを設定する方法(クリックで展開)

SSLContextを設定する方法

以下のように、context を設定してhttpsアクセスする。

urllib.request.urlopen(https_url, context=ssl.create_default_context(cafile=certifi.where()))

もちろん、certifi管理の pem が存在していることが前提。(以下コマンドで確認可能)

python -c "import certifi;print(certifi.where())"

+ C. 証明書チェックを無視する方法(クリックで展開)

証明書チェックを無視する方法

オススメではないが、feedparser のように SSLContext を設定できない場合に使う。
以下コードを feedparser.parse より前に記述。

if hasattr(ssl, '_create_unverified_context'):
    ssl._create_default_https_context = ssl._create_unverified_context

 備考

  • REQUESTS_CA_BUNDLE を設定してもダメだった
  • デフォルト挙動の openssl_cafile がそもそも機能していないので、これを何とかする方法はないのか?
    • OpenSSL を openssl_cafile のパス指定でインストールし直すとか
    • 環境変数で openssl_cafile を設定するとか(Windows の環境変数 OPENSSL_CAFILE を設定してもダメだった)

-ブログ

© 2022 墾田ええねん! Powered by AFFINGER5