在 Facebook 图 api 上使用 twisted.web.client.Agent 时如何处理 OpenSSL.SSL.Error?

How to handle OpenSSL.SSL.Error while using twisted.web.client.Agent on Facebook graph api?

我是运行 ff。来自 Mac OS X (Yosemite):

上的 virtualenv 的代码
    # testfb.py
    from twisted.internet import reactor
    from twisted.python import log
    from twisted.web.client import Agent

    GRAPH_API = "https://graph.facebook.com/v2.5"

    def stop(_):
        reactor.stop()

    def get_me(access_token):
        agent = Agent(reactor)
        uri = "{}/me?access_token={}".format(GRAPH_API, access_token)
        log.msg("uri:" + uri)
        return agent.request("GET", uri)

    if __name__ == "__main__":
        import sys
        access_token = sys.argv[1]
        d = get_me(access_token)
        d.addErrback(log.err)
        d.addCallback(stop)
        reactor.run()

我得到:

    Failure: twisted.web._newclient.ResponseNeverReceived: [<twisted.python.failure.Failure OpenSSL.SSL.Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE', 'certificate verify failed')]>]

我在 curl 中调用 uri 时没有这个问题。

顺便说一句,我还在 virtualenv 上使用 pip 安装了 service_identity。

您可能没有配置任何 OpenSSL 信任根。这曾经是偶然自动发生的,因为 Cryptography 链接到来自 OS X 的 built-in 版本的 OpenSSL。由于该版本的 headers 在 El Capitan 中被删除,现在密码学附带自己的 built-in 版本的 pyOpenSSL。

这是 Twisted 中的一个错误,我们知道;你可以在这里阅读更多相关信息:https://twistedmatrix.com/trac/ticket/6372。它已经开放了一段时间;因为它偶然工作了很长时间,所以一直没有高优先级。感谢像您这样的人的错误报告,这正在改变...

不过,与此同时,您有两个可能的选择。

一个是您可以从 Homebrew 安装 OpenSSL,它会自动将一些证书颁发机构证书放在 Cryptography 的 OpenSSL 已经在寻找它们的默认位置,brew install openssl。 (安装后可以在/usr/local/etc/openssl/cert.pem中看到这些证书颁发机构证书)

另一个是您可以从 Certifi, and then set the (undocumented) 环境变量中获取一些证书,这些证书告诉 OpenSSL 查找它们,例如,在调用之前在您的 shell 中执行 export SSL_CERT_FILE="$(python -m certifi)"你的 Python 程序。

抱歉,我希望这能回答您的问题!