【问题标题】:Windows 2019, Python 3.9.7, urllib, certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)Windows 2019,Python 3.9.7,urllib,证书验证失败:无法获取本地颁发者证书 (_ssl.c:1129)
【发布时间】:2021-09-27 15:28:45
【问题描述】:

Windows 2019 上的 Python 脚本对我来说开始失败,显然是由于本地信任库出现问题,我似乎无法正确处理。

堆栈跟踪

C:\tmp\DEL (master -> origin)
λ python
Python 3.9.7 (tags/v3.9.7:1016ef3, Aug 30 2021, 20:19:38) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import urllib.request;file_name, headers = urllib.request.urlretrieve("https://repo1.maven.org/fromsearch?filepath=org/antlr/antlr4-runtime/4.9.2/antlr4-runtime-4.9.2.jar");println(file_name);
Traceback (most recent call last):
  File "C:\Python39\lib\urllib\request.py", line 1346, in do_open
    h.request(req.get_method(), req.selector, req.data, headers,
  File "C:\Python39\lib\http\client.py", line 1279, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "C:\Python39\lib\http\client.py", line 1325, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "C:\Python39\lib\http\client.py", line 1274, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "C:\Python39\lib\http\client.py", line 1034, in _send_output
    self.send(msg)
  File "C:\Python39\lib\http\client.py", line 974, in send
    self.connect()
  File "C:\Python39\lib\http\client.py", line 1448, in connect
    self.sock = self._context.wrap_socket(self.sock,
  File "C:\Python39\lib\ssl.py", line 500, in wrap_socket
    return self.sslsocket_class._create(
  File "C:\Python39\lib\ssl.py", line 1040, in _create
    self.do_handshake()
  File "C:\Python39\lib\ssl.py", line 1309, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python39\lib\urllib\request.py", line 239, in urlretrieve
    with contextlib.closing(urlopen(url, data)) as fp:
  File "C:\Python39\lib\urllib\request.py", line 214, in urlopen
    return opener.open(url, data, timeout)
  File "C:\Python39\lib\urllib\request.py", line 517, in open
    response = self._open(req, data)
  File "C:\Python39\lib\urllib\request.py", line 534, in _open
    result = self._call_chain(self.handle_open, protocol, protocol +
  File "C:\Python39\lib\urllib\request.py", line 494, in _call_chain
    result = func(*args)
  File "C:\Python39\lib\urllib\request.py", line 1389, in https_open
    return self.do_open(http.client.HTTPSConnection, req,
  File "C:\Python39\lib\urllib\request.py", line 1349, in do_open
    raise URLError(err)
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)>
>>>

上下文

我尝试更新 Python 证书,例如

    Start-Process -Wait -FilePath "C:\Python39\python.exe" -ArgumentList "-m","pip","install","--upgrade","pip"
    Start-Process -Wait -FilePath "C:\Python39\python.exe" -ArgumentList "-m","pip","install","python-certifi-win32"
    Start-Process -Wait -FilePath "C:\Python39\python.exe" -ArgumentList "-m","pip","install","--upgrade","certifi"

我也尝试下载证书链并做:

set REQUESTS_CA_BUNDLE=C:\tmp\repo1-maven-org-chain.pem

最后但并非最不重要的一点是,出于绝望,我也尝试过(尽管我不希望将其作为“解决方案”):

set PYTHONHTTPSVERIFY=0

关于更多上下文,我在安装过程中更新系统证书存储:

function Import-509Certificate([String]$certPath,[String]$certRootStore,[String]$certStore,[String]$myAlias) {
    # Windows keystore
    $pfx = new-object System.Security.Cryptography.X509Certificates.X509Certificate2
    $pfx.import($certPath)
    $store = new-object System.Security.Cryptography.X509Certificates.X509Store($certStore,$certRootStore)
    $store.open("MaxAllowed")
    $store.add($pfx)
    $store.close()

    # Java store
    $javaStores = @(
        "C:\Program Files\openjdk-11\lib\security\cacerts"
        "C:\Program Files\openjdk-8\jre\lib\security\cacerts"
    )
    foreach($store in $javaStores) {
        Start-Process -Wait -FilePath "C:\Program Files\openjdk-8\bin\keytool" -ArgumentList "-noprompt","-importcert","-alias","`"$myAlias`"","-keystore","`"$store`"","-storepass","changeit","-file","`"$certPath`""
    }
}

function Install-Certs() {
    $letsEncryptCerts = @(
    "https://letsencrypt.org/certs/isrgrootx1.pem"
    "https://letsencrypt.org/certs/isrg-root-x1-cross-signed.pem"
    "https://letsencrypt.org/certs/lets-encrypt-r3.pem"
    "https://letsencrypt.org/certs/lets-encrypt-r3-cross-signed.pem"
    "https://letsencrypt.org/certs/lets-encrypt-e1.pem"
    )
    foreach($url in $letsEncryptCerts) {
        $certFile = $(Split-Path -Path $url -Leaf)
        Write-Host "Downloading $url to C:\tmp\$certFile"
        $wc.DownloadFile($url, "C:\tmp\$certFile")
        Import-509Certificate "C:\tmp\$certFile" "LocalMachine" "Root" $certFile
    }
    Import-509Certificate "C:\cygwin64\tmp\legacy.pem" "LocalMachine" "Root" "rh_it_legacy"
    Import-509Certificate "C:\cygwin64\tmp\maven-org-chain.pem" "LocalMachine" "Root" "maven_org_chain"
}

我不是 Python 或 Windows 用户,但我知道 Python 运行时本身有自己的信任库,独立于系统信任库。

是否有任何可能有帮助的干净解决方案? 我不是要关闭信任链验证。我正在寻找一种更新信任库以使 Python 运行时信任签名的方法。

安装在该 Windows 系统上的最新更新的 Firefox 信任该站点 (https://repo1.maven.org) 而不会发出任何警告。

【问题讨论】:

    标签: python python-3.x windows https urllib


    【解决方案1】:

    问题解决了。现代 Python,例如问题中使用的版本,即 3.7.9 实际上是使用 Windows 自己的信任库。

    下载正确的 GlobalSign 证书并将它们作为“TrustedPublisher”存储在信任库中解决了这个问题:

    "https://secure.globalsign.net/cacert/Root-R1.crt"
    "https://secure.globalsign.net/cacert/Root-R3.crt"
    

    $store = New-Object System.Security.Cryptography.X509Certificates.X509Store "TrustedPublisher","LocalMachine"
    $store.Open("ReadWrite")
    $store.Add($certPath)
    $store.Close()
    

    Python 现在很高兴地信任该站点:

    >>> import urllib.request;file_name, headers = urllib.request.urlretrieve("https://repo1.maven.org/fromsearch?filepath=org/antlr/antlr4-runtime/4.9.2/antlr4-runtime-4.9.2.jar");print(file_name);
    
    C:\Users\ADMINI~1\AppData\Local\Temp\2\tmpvc1zkphg
    

    【讨论】:

    • 在我的情况下,我所要做的就是下载这两个文件,双击证书,安装它们,然后 python 又开心了。
    猜你喜欢
    • 2021-11-25
    • 2020-04-12
    • 1970-01-01
    • 2020-12-13
    • 1970-01-01
    • 1970-01-01
    • 2019-03-19
    相关资源
    最近更新 更多