简体   繁体   English

python httplib2 证书验证失败

[英]python httplib2 certificate verify failed

I have tried everything I can find to get this to work...我已经尝试了我能找到的一切来让它工作......

I'm working on a plugin for a python-based task program (called GTG).我正在为基于 python 的任务程序(称为 GTG)开发一个插件。 I'm running Gnome on Opensuse Linux.我在 Opensuse Linux 上运行 Gnome。

Code (Python 2.7):代码(Python 2.7):

def initialize(self):
    """
    Intialize backend: try to authenticate. If it fails, request an authorization.
    """
    super(Backend, self).initialize()
    path = os.path.join(CoreConfig().get_data_dir(), 'backends/gtask', 'storage_file-%s' % self.get_id())
    # Try to create leading directories that path
    path_dir = os.path.dirname(path)
    if not os.path.isdir(path_dir):
        os.makedirs(path_dir)

    self.storage = Storage(path)
    self.authenticate()

def authenticate(self):
    """ Try to authenticate by already existing credences or request an authorization """
    self.authenticated = False

    credentials = self.storage.get()
    if credentials is None or credentials.invalid == True:
        self.request_authorization()
    else:
        self.apply_credentials(credentials)
        # Request periodic import, avoid waiting a long time
        # self.start_get_tasks()

def apply_credentials(self, credentials):
    """ Finish authentication or request for an authorization by applying the credentials """


    http = httplib2.Http(ca_certs = '/etc/ssl/certs/ca_certs.pem', disable_ssl_certificate_validation=True)

    http = credentials.authorize(http)

    # Build a service object for interacting with the API.
    self.service = build_service(serviceName='tasks', version='v1', http=http, developerKey='AIzaSyAmUlk8_iv-rYDEcJ2NyeC_KVPNkrsGcqU')
    # self.service = build_service(serviceName='tasks', version='v1')
    self.authenticated = True

def _authorization_step2(self, code):
    credentials = self.flow.step2_exchange(code)
    # credential = self.flow.step2_exchange(code)

    self.storage.put(credentials)
    credentials.set_store(self.storage)

    return credentials

def request_authorization(self):
    """ Make the first step of authorization and open URL for allowing the access """

    self.flow = OAuth2WebServerFlow(client_id=self.CLIENT_ID,
        client_secret=self.CLIENT_SECRET,
        scope='https://www.googleapis.com/auth/tasks',
        redirect_uri='http://localhost:8080',
        user_agent='GTG')


    oauth_callback = 'oob'
    auth_uri = self.flow.step1_get_authorize_url(oauth_callback)
    # credentials = self.flow.step2_exchange(code)



    # url = self.flow.step1_get_authorize_url(oauth_callback)
    browser_thread = threading.Thread(target=lambda: webbrowser.open_new(auth_uri))
    browser_thread.daemon = True
    browser_thread.start()

    # Request the code from user
    BackendSignals().interaction_requested(self.get_id(), _(
        "You need to <b>authorize GTG</b> to access your tasks on <b>Google</b>.\n"
        "<b>Check your browser</b>, and follow the steps there.\n"
        "When you are done, press 'Continue'."),
        BackendSignals().INTERACTION_TEXT,
        "on_authentication_step")


def on_authentication_step(self, step_type="", code=""):

    if step_type == "get_ui_dialog_text":
        return _("Code request"), _("Paste the code Google has given you"
                "here")
    elif step_type == "set_text":
        try:

            credentials = self._authorization_step2(code)
        except FlowExchangeError, e:
            # Show an error to user and end
            self.quit(disable = True)
            BackendSignals().backend_failed(self.get_id(), 
                        BackendSignals.ERRNO_AUTHENTICATION)
            return

        self.apply_credentials(credentials)
        # Request periodic import, avoid waiting a long time
        self.start_get_tasks()

The browser window opens up and I am presented with a code from Google.浏览器 window 打开,我看到了来自 Google 的代码。 The program opens a small window where I can enter the code from Google.When that happens I get this in the console:该程序会打开一个小的 window,我可以在其中输入来自 Google 的代码。发生这种情况时,我会在控制台中得到这个:

 No handlers could be found for logger "oauth2client.util"
Created new window in existing browser session.
[522:549:0108/063825:ERROR:nss_util.cc(821)] After loading Root Certs, loaded==false: NSS error code: -8018

but the SSL icon is green in Chrome...但是 SSL 图标在 Chrome 中是绿色的...

then when I submit the code, I get:然后当我提交代码时,我得到:

    Exception in thread Thread-10:
Traceback (most recent call last):
  File "/usr/lib64/python2.7/threading.py", line 810, in __bootstrap_inner
    self.run()
  File "/usr/lib64/python2.7/threading.py", line 763, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/usr/lib/python2.7/site-packages/GTG/backends/backend_gtask.py", line 204, in on_authentication_step
    credentials = self._authorization_step2(code)
  File "/usr/lib/python2.7/site-packages/GTG/backends/backend_gtask.py", line 151, in _authorization_step2
    credentials = self.flow.step2_exchange(code)
  File "/usr/lib/python2.7/site-packages/oauth2client/util.py", line 132, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/usr/lib/python2.7/site-packages/oauth2client/client.py", line 1283, in step2_exchange
    headers=headers)
  File "/usr/lib/python2.7/site-packages/httplib2/__init__.py", line 1586, in request
    (response, content) = self._request(conn, authority, uri, request_uri, method, body, headers, redirections, cachekey)
  File "/usr/lib/python2.7/site-packages/httplib2/__init__.py", line 1328, in _request
    (response, content) = self._conn_request(conn, request_uri, method, body, headers)
  File "/usr/lib/python2.7/site-packages/httplib2/__init__.py", line 1250, in _conn_request
    conn.connect()
  File "/usr/lib/python2.7/site-packages/httplib2/__init__.py", line 1037, in connect
    raise SSLHandshakeError(e)
SSLHandshakeError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:581)

The file is called backend_gtask.py...该文件名为 backend_gtask.py ...

I have tried importing the certificate as stated here: How to update cacerts.txt of httplib2 for Github?我已尝试按照此处所述导入证书: How to update cacerts.txt of httplib2 for Github?

I have tried to disable verification (httplib2.Http(disable_ssl_certificate_validation=True)) as stated all over the web,我试图禁用验证 (httplib2.Http(disable_ssl_certificate_validation=True)),如 web 所述,

I have updated the python packages (which seemed to make things worse)我已经更新了 python 包(这似乎让事情变得更糟)

I have copied ca_certs.pem back and forth between /etc/ssl... and /usr/lib/python2.7/...我在 /etc/ssl... 和 /usr/lib/python2.7/... 之间来回复制了 ca_certs.pem

When I visit the auth page in a browser, it says the certificate is verified...当我在浏览器中访问身份验证页面时,它说证书已验证...

What else can I possibly check?我还能检查什么?

SHORT TEST CODE:简短的测试代码:

from oauth2client.client import OAuth2WebServerFlow
from oauth2client.tools import run
from oauth2client.file import Storage

CLIENT_ID = 'id'
CLIENT_SECRET = 'secret'

flow = OAuth2WebServerFlow(client_id=CLIENT_ID,
                           client_secret=CLIENT_SECRET,
                           scope='https://www.googleapis.com/auth/tasks',
                           redirect_uri='http://localhost:8080')

storage = Storage('creds.data')

credentials = run(flow, storage)

print "access_token: %s" % credentials.access_token

Found that here: https://github.com/burnash/gspread/wiki/How-to-get-OAuth-access-token-in-console%3F在这里发现: https://github.com/burnash/gspread/wiki/How-to-get-OAuth-access-token-in-console%3F

OK... Big thanks to Steffen Ullrich.好的...非常感谢 Steffen Ullrich。

httplib2 version 0.9 tries to use the system certificates and not the certs.txt file that used to be shipped with it. httplib2 0.9 版尝试使用系统证书而不是过去随附的 certs.txt 文件。 It also enforces verification.它还强制执行验证。

httplib2 can take a couple of useful parameters - notably ca_certs. httplib2 可以采用几个有用的参数 - 特别是 ca_certs。 Use it to point to the actual *.pem file in you ssl installation.使用它来指向 ssl 安装中的实际 *.pem 文件。 I cannot be a folder, must be a real file.我不能是一个文件夹,必须是一个真实的文件。

I use the following in the initialization of the plugin :我在插件的初始化中使用以下内容:

self.http = httplib2.Http(ca_certs = '/etc/ssl/ca-bundle.pem')

Then, for all subsequent calls to httplib or google client libraries, I pass my pre-built http object as a parameter like this:然后,对于对 httplib 或 google 客户端库的所有后续调用,我将预构建的 http 对象作为参数传递,如下所示:

credentials = self.flow.step2_exchange(code, self.http)

self.http = credentials.authorize(self.http)

Now ssl connections work with the new httplib2...现在 ssl 连接可以与新的 httplib2 一起使用...

I will eventually have to make sure the plugin can find certificates on any system, but at least I know what the problem was.我最终必须确保插件可以在任何系统上找到证书,但至少我知道问题出在哪里。

Thanks again to Steffen Ullrich for walking me through this.再次感谢Steffen Ullrich 带领我完成了这一切。

See this answer for an easier fix without touching your code: just set your certificate bundle pem file path in an environment variable:请参阅此答案以获得更简单的修复,而无需接触您的代码:只需在环境变量中设置您的证书捆绑 pem 文件路径:

export HTTPLIB2_CA_CERTS="\path\to\your\ca-bundle"

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

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