【发布时间】: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