简体   繁体   English

修复使用 py2exe(或 PyInstaller)编译的 exe 中的 SSL 证书错误

[英]Fixing SSL certificate error in exe compiled with py2exe (or PyInstaller)

I've just finished testing a Python programme which involves logging into a site and requires a CSRF cookie to be set.我刚刚完成了一个 Python 程序的测试,该程序涉及登录站点并需要设置 CSRF cookie。 I've tried packaging it as an exe using py2exe and got a socket error.我尝试使用py2exe其打包为 exe 并出现套接字错误。 I have the same problem when I try with PyInstaller .当我尝试使用PyInstaller时,我PyInstaller了同样的问题。 Googling the Errno I found a few other people with the same problem and so I know the problem is to do with the location of SLL certificates.谷歌搜索 Errno 我发现其他一些人也有同样的问题,所以我知道问题与 SLL 证书的位置有关。

This is my site_agent class including the logging calls.这是我的site_agent类,包括日志记录调用。

    class site_agent:
        self.get_params()
        URL = root_url + '/accounts/login/'        
        # Retrieve the CSRF token first
        self.agent = requests.session()
        self.agent.get(URL)  # retrieves the cookie # This line throws the error
        self.csrftoken = self.agent.cookies['csrftoken']    
        # Set up login data including the CSRF cookie
        login_data = {'username': self.username,
                      'password': self.password,
                      'csrfmiddlewaretoken' : self.csrftoken}
        # Log in
        logging.info('Logging in')
        response = self.agent.post(URL, data=login_data, headers=hdr)

The error comes at the self.agent.get(URL) line and the Traceback shows:错误出现在self.agent.get(URL)行和 Traceback 显示:

Traceback (most recent call last):
  File "<string>", line 223, in <module>
  File "<string>", line 198, in main
  File "<string>", line 49, in __init__
  File "C:\pyinstaller-2.0\pyinstaller-2.0\autoresponder\b
uild\pyi.win32\autoresponder\out00-PYZ.pyz\requests.sessions", line 350, in get
  File "C:\pyinstaller-2.0\pyinstaller-2.0\autoresponder\b
uild\pyi.win32\autoresponder\out00-PYZ.pyz\requests.sessions", line 338, in requ
est
  File "C:\pyinstaller-2.0\pyinstaller-2.0\autoresponder\b
uild\pyi.win32\autoresponder\out00-PYZ.pyz\requests.sessions", line 441, in send

  File "C:\pyinstaller-2.0\pyinstaller-2.0\autoresponder\b
uild\pyi.win32\autoresponder\out00-PYZ.pyz\requests.adapters", line 331, in send

requests.exceptions.SSLError: [Errno 185090050] _ssl.c:336: error:0B084002:x509
certificate routines:X509_load_cert_crl_file:system lib

Does this mean that the problem is in requests.adapters ?这是否意味着问题出在requests.adapters

If so, can I just edit it in my installed Python packages to look for cacert.pem somewhere else, rebuild my exe with py2exe or PyInstaller , then change it back in my installed version of Python?如果是这样,我是否可以在我安装的 Python 包中编辑它以在其他地方查找 cacert.pem,使用py2exePyInstaller重建我的 exe,然后在我安装的 Python 版本PyInstaller其改回?

EDIT编辑

I now have the programme running after compiling with PyInstaller and setting verify=False in all requests.get() and requests.post() calls.我现在在使用PyInstaller编译并在所有requests.get()requests.post()调用中设置verify=False后运行程序。 But SSL is there for aa reason and I'd really like to be able to fix this error before letting anyone use the tool.但是 SSL 存在是有原因的,我真的希望能够在让任何人使用该工具之前修复此错误。

If using pyinstaller... create a hook-requests.py file in PyInstaller\\hooks\\ for the requests lib containing如果使用 pyinstaller... 在PyInstaller\\hooks\\为包含的请求库创建一个hook-requests.py文件

from hookutils import collect_data_files

# Get the cacert.pem
datas = collect_data_files('requests') 

This can be solved easily if you are using "requests" module.如果您使用“请求”模块,这可以轻松解决。

1) Place the below code in your main python file where "requests" module is used 1)将以下代码放在使用“请求”模块的主python文件中

os.environ['REQUESTS_CA_BUNDLE'] = "certifi/cacert.pem"

2) Within your distributable folder where exe is present, create a folder called "certifi" and place the "cacert.pem" file within it. 2) 在 exe 所在的可分发文件夹中,创建一个名为“certifi”的文件夹,并将“cacert.pem”文件放入其中。

3) You can find the "cacert.pem" file by 3)您可以通过以下方式找到“cacert.pem”文件

pip install certifi

import certifi
certifi.where()

Awesome.. now your distributable includes the necessary certificates to validate ssl calls.太棒了.. 现在您的发行版包括验证 ssl 调用所需的证书。

In addition to the answer given by frmdstryr , I had to tell requests where the cacert.pem is.除了frmdstryr给出的答案frmdstryr ,我还必须告诉requests cacert.pem在哪里。 I added the following lines right after my imports:我在导入后立即添加了以下几行:

# Get the base directory
if getattr( sys , 'frozen' , None ):    # keyword 'frozen' is for setting basedir while in onefile mode in pyinstaller
    basedir = sys._MEIPASS
else:
    basedir = os.path.dirname( __file__ )
    basedir = os.path.normpath( basedir )

# Locate the SSL certificate for requests
os.environ['REQUESTS_CA_BUNDLE'] = os.path.join(basedir , 'requests', 'cacert.pem')

This solution is derived from this link: http://kittyandbear.net/python/pyinstaller-request-sslerror-manual-cacert-solution.txt此解决方案源自此链接: http : //kittyandbear.net/python/pyinstaller-request-sslerror-manual-cacert-solution.txt

I was struggling with this as well, The hook-requests.py provided by frmdstryr did not work for me.我也在为此苦苦挣扎, hook-requests.py提供的frmdstryr对我不起作用。 But this modified one did:但是这个修改过的做了:

from PyInstaller.utils.hooks import collect_data_files

# Get the cacert.pem
datas = collect_data_files('certifi')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM