对于经过身份验证的SSL,Python urllib2 / httplib始终返回400

时间:2014-11-09 21:07:20

标签: python nginx urllib2 python-requests httplib

我使用的是一个普遍使用经过身份验证的SSL的庞大系统,并且它已经完美地运行了五个月。我在本地系统上安装了整个生态系统(Mac 10.9.5)。在本地运行时,它仍然使用经过身份验证的SSL连接,但由于显而易见的原因,服务器证书的SSL验证已关闭。

我使用 requests 在本地系统和服务器上建立与Nginx网络服务器的连接。

星期五,我开始在我的本地系统上从客户端的请求获得400。我做了一些更改,但我使用的是早期版本,但没有任何区别。据我所知,我没有改变环境。

为了验证是不是导致破坏的自动Apple更新,我使用Vagrant配置了Ubuntu 12.04(Python 2.7.3)和14.04(Python 2.7.6)环境。虽然它消除了一些变量,但事情仍然无效。

奇怪的是,使用cURL可以直接使用,但使用 urllib2 / httplib (由请求调用)仍然可以让我400。

它已经被Python 2.7破坏了,但Python 3.4仍然可以正常工作。

cURL(作品):

curl -s -v -X GET -k --cert /var/lib/rt_data/ssl/rt.crt.pem --key /var/lib/rt_data/ssl/rt.private_key.pem https://deploy_api.local:8443/auth/admin/1/hosts
Python下的

urllib2 / httplib (已损坏):

#!/usr/bin/env python2.7

import urllib2
import httplib

cert_filepath = '/var/lib/rt_data/ssl/rt.crt.pem'
key_filepath = '/var/lib/rt_data/ssl/rt.private_key.pem'

url = 'https://deploy_api.local:8443/auth/admin/1/hosts'


class HTTPSClientAuthHandler(urllib2.HTTPSHandler):
    """Wrapper to allow for authenticated SSL connections."""

    def __init__(self, key, cert):
        urllib2.HTTPSHandler.__init__(self)
        self.key = key
        self.cert = cert

    def https_open(self, req):
        # Rather than pass in a reference to a connection class, we pass in
        # a reference to a function which, for all intents and purposes,
        # will behave as a constructor
        return self.do_open(self.getConnection, req)

    def getConnection(self, host, timeout=300):
        return httplib.HTTPSConnection(host, key_file=self.key, cert_file=self.cert)

opener = urllib2.build_opener(HTTPSClientAuthHandler(key_filepath, cert_filepath))
response = opener.open(url)

response_data = response.read()
print(response_data)

仍然适用于Python 3.4。这使用请求(我们更喜欢这样),因为 urllib2 不再可用于我们在Python 3.4下的实验:

import requests

cert_filepath = '/var/lib/rt_data/ssl/rt.crt.pem'
key_filepath = '/var/lib/rt_data/ssl/rt.private_key.pem'

url = 'https://deploy_api.local:8443/auth/admin/1/hosts'

r = requests.get(url, 
                 cert=(cert_filepath, key_filepath),
                 verify=False)

作为参考,这是Nginx配置:

server {
    listen      8443 ssl;

    ssl on;
    ssl_certificate     /vagrant/ssl/deploy/deploy_api.crt.pem;
    ssl_certificate_key /vagrant/ssl/deploy/deploy_api.key.pem;

    ssl_client_certificate /vagrant/ssl/ca_cert.pem;
    ssl_verify_client on;
    ssl_verify_depth 1;

    location ^~ /auth/ {
        # ...
    }

    location / {
        return 403;
    }
}

如果我发表评论ssl_verify_client,它将通过,但不会处理客户证书。

获得400时的回复是:

vagrant@deploy:/deployment/deploy_scripts/dev$ ./curl_ds_host_shell.py 
<html>
<head><title>400 No required SSL certificate was sent</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<center>No required SSL certificate was sent</center>
<hr><center>nginx/1.4.6 (Ubuntu)</center>
</body>
</html>

因此,我认为 urllib2 / httplib 由于某种原因省略了证书。但是,客户端仍然可以从我的本地计算机和Vagrant下的Ubuntu实例工作到生产服务器。只有在Mac Vagrant实例下的本地服务器才会出现这种情况。

有没有人任何想法发生了什么?

0 个答案:

没有答案