如何让Python使用Windows证书存储或自动更新certifi cacert.pem?
Python在Windows下使用系统证书存储的解决方案
1. 让Python直接使用Windows证书存储
完全可以实现,推荐两种高效方式:
- 使用
certifi-win32第三方库:这是最简便的方案,安装后会自动让Python的SSL操作优先调用Windows系统的受信任根证书存储,无需手动修改任何文件。
安装命令:
安装完成后,Python的pip install certifi-win32requests、urllib等依赖SSL的库会自动使用Windows证书,和浏览器等应用保持一致。 - 手动实现证书读取:通过
pywin32库读取Windows根证书存储,生成自定义SSL上下文供请求使用。示例代码:import ssl import win32crypt import requests def get_system_root_certs(): # 打开系统根证书存储 store = win32crypt.CertOpenSystemStore(0, "ROOT") cert_pems = [] cert = win32crypt.CertEnumCertificatesInStore(store, None) while cert: # 提取DER格式证书并转为PEM der_cert = win32crypt.CertGetCertificateContextProperty(cert, win32crypt.CERT_ENCODED_PROP_ID) cert_pems.append(ssl.DER_cert_to_PEM_cert(der_cert)) cert = win32crypt.CertEnumCertificatesInStore(store, cert) win32crypt.CertCloseStore(store, 0) return "\n".join(cert_pems) # 创建加载系统证书的SSL上下文 ssl_ctx = ssl.create_default_context() ssl_ctx.load_verify_locations(cadata=get_system_root_certs()) # 使用该上下文发起请求 resp = requests.get("https://your-target-url.com", verify=ssl_ctx)
2. 避免重复维护证书的最优方案
直接采用上述certifi-win32的方案即可,它会自动桥接Python的SSL层和Windows证书存储,后续系统证书的更新(比如新增根CA)会自动同步到Python应用中,完全无需手动维护cacert.pem,从根源上消除冗余和错误风险。
3. 同步Windows证书到certifi的cacert.pem
Certifi官方本身没有提供同步命令,但可以通过脚本或系统命令实现:
- 系统命令方式:
- 用
certutil导出系统根证书到临时文件:certutil -store root temp_certs.pem - 备份原cacert.pem后,合并临时文件到cacert.pem(替换下方路径为你的certifi实际路径):
copy "C:\PythonXX\Lib\site-packages\certifi\cacert.pem" "C:\PythonXX\Lib\site-packages\certifi\cacert_backup.pem" copy /b "C:\PythonXX\Lib\site-packages\certifi\cacert.pem" + temp_certs.pem "C:\PythonXX\Lib\site-packages\certifi\cacert.pem"
- 用
- Python脚本自动同步:
注意:这种方式的缺陷是,当Certifi库更新时,cacert.pem会被覆盖,需要重新同步,因此不如直接使用系统证书存储的方案持久。import certifi import ssl import win32crypt def sync_windows_certs(): # 获取Windows根证书 store = win32crypt.CertOpenSystemStore(0, "ROOT") cert_pems = [] cert = win32crypt.CertEnumCertificatesInStore(store, None) while cert: der_cert = win32crypt.CertGetCertificateContextProperty(cert, win32crypt.CERT_ENCODED_PROP_ID) cert_pems.append(ssl.DER_cert_to_PEM_cert(der_cert)) cert = win32crypt.CertEnumCertificatesInStore(store, cert) win32crypt.CertCloseStore(store, 0) # 读取原cacert内容并合并去重 with open(certifi.where(), "r", encoding="utf-8") as f: original_content = f.read() combined = original_content + "\n\n" + "\n\n".join(cert_pems) # 去重避免重复证书 unique_certs = list(dict.fromkeys(combined.split("\n\n"))) final_content = "\n\n".join(unique_certs) # 写入回cacert.pem with open(certifi.where(), "w", encoding="utf-8") as f: f.write(final_content) if __name__ == "__main__": sync_windows_certs()
内容的提问来源于stack exchange,提问作者geekygeek
相关产品推荐
相关产品推荐

