【问题标题】:HTTPS connection using PEM Certificate使用 PEM 证书的 HTTPS 连接
【发布时间】:2011-08-19 06:39:06
【问题描述】:

我正在尝试使用 PEM 证书发布 HTTPS 请求,如下所示:

import httplib  
CERT_FILE = '/path/certif.pem'
conn = httplib.HTTPSConnection('10.10.10.10','443', cert_file =CERT_FILE)   
conn.request("POST", "/") 
response = conn.getresponse()       
print response.status, response.reason
conn.close()

我有以下错误:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.6/httplib.py", line 914, in request
self._send_request(method, url, body, headers)
File "/usr/lib/python2.6/httplib.py", line 951, in _send_request
self.endheaders()
File "/usr/lib/python2.6/httplib.py", line 908, in endheaders
self._send_output()
File "/usr/lib/python2.6/httplib.py", line 780, in _send_output
self.send(msg)
File "/usr/lib/python2.6/httplib.py", line 739, in send
self.connect()
File "/usr/lib/python2.6/httplib.py", line 1116, in connect
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file)
File "/usr/lib/python2.6/ssl.py", line 338, in wrap_socket
suppress_ragged_eofs=suppress_ragged_eofs)
File "/usr/lib/python2.6/ssl.py", line 118, in __init__
cert_reqs, ssl_version, ca_certs)
ssl.SSLError: [Errno 336265225] _ssl.c:339: error:140B0009:SSL       
routines:**SSL_CTX_use_PrivateKey_file**:PEM lib

当我从 httplib 中删除 cert_file 时,我得到以下响应:

200 ok

当我添加带有空 post 有效负载的 Authentication 标头(如 MattH 建议的)时,它也可以工作。

但是,当我将良好的请求与 Path、Body 和 Header 一起提出时,如下所示(我简化了它们......)

body = '<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">blablabla</S:Envelope>'
URLprov = "/syncaxis2/services/XXXsyncService"
auth_header = 'Basic %s' %  (":".join(["xxx","xxxxx"]).encode('Base64').strip('\r\n'))
conn.request("POST",URLprov,body,{'Authenticate':auth_header})

我有 401 Unauthorized response!

如您所见,首先,我被要求提供 PrivateKey !如果我是客户,为什么需要 PrivateKey?然后,当我删除 PrivateKey 和证书,并放置 Path/Body/headers 时,我有 401 Unauthorized 错误消息 WWW-Authenticate: Basic realm="SYNCNB Server Realm"。

谁能解释一下这个问题?在 Python 中是否有另一种使用证书发送 HTTPS 请求的方法?

【问题讨论】:

    标签: python ssl https certificate


    【解决方案1】:

    听起来您需要类似于我之前提供的答案来执行simple client certificate authentication。以下是为方便起见针对您的问题稍作修改的代码:

    import httplib
    import urllib2
    
    PEM_FILE = '/path/certif.pem' # Renamed from PEM_FILE to avoid confusion
    CLIENT_CERT_FILE = '/path/clientcert.p12' # This is your client cert!
    
    # HTTPS Client Auth solution for urllib2, inspired by
    # http://bugs.python.org/issue3466
    # and improved by David Norton of Three Pillar Software. In this
    # implementation, we use properties passed in rather than static module
    # fields.
    class HTTPSClientAuthHandler(urllib2.HTTPSHandler):
        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):
            return httplib.HTTPSConnection(host, key_file=self.key, cert_file=self.cert)
    
    
    cert_handler = HTTPSClientAuthHandler(PEM_FILE, CLIENT_CERT_FILE)
    opener = urllib2.build_opener(cert_handler)
    urllib2.install_opener(opener)
    
    f = urllib2.urlopen("https://10.10.10.10")
    print f.code
    

    【讨论】:

    • 嗨 jathanism,事实上,我只有 client_cert_file.pem(一个 base64 文件),因为我是将连接到服务器的客户端,我想使用它来发送 HTTPS向服务器请求。也许我没有使用使用 SSL PEM 证书询问服务器的好方法?
    • @jathanism 您的代码正在抛出错误。 TypeError: getConnection() 得到了一个意外的关键字参数“超时”
    • 您可以通过将行更改为getConnection(self, host, timeout=300):来解决此问题
    【解决方案2】:

    http://docs.python.org/library/httplib.html

    httplib.HTTPSConnection 不对服务器的证书做任何验证。

    包含您的私有证书的选项是在服务器对客户端进行基于证书的身份验证时。 IE。服务器正在检查客户端是否有一个由它信任的 CA 签名的证书,并且允许访问它的资源。


    如果您不指定 cert 可选参数,您应该能够连接到 HTTPS 服务器,但不会验证服务器证书。


    更新

    根据您已尝试基本身份验证的评论,服务器似乎仍希望您使用基本身份验证进行身份验证。您的凭据无效(您是否独立验证过它们?)或者您的 Authenticate 标头格式不正确。修改您的示例代码以包含一个基本的身份验证标头和一个空的 post 有效负载:

    import httplib  
    conn = httplib.HTTPSConnection('10.10.10.10','443')   
    auth_header = 'Basic %s' % (":".join(["myusername","mypassword"]).encode('Base64').strip('\r\n'))
    conn.request("POST", "/","",{'Authorization':auth_header}) 
    response = conn.getresponse()       
    print response.status, response.reason
    conn.close()
    

    【讨论】:

    • 嗨,MattH,事实上,当我没有指定 cert 可选参数时,我的响应是 401 Unauthorized... 你能告诉我如何验证我的证书吗?被远程服务器接受?非常感谢您的帮助
    • @psikais:该服务需要某种形式的身份验证。检查服务器 401 响应中的“WWW-Authenticate”标头以获取有关它支持哪些身份验证方案的更多信息。
    • @MattH,我收到错误消息“WWW-Authenticate: Basic realm="SYNCNB Server Realm"。另外,正如我告诉你的,我没有在任何地方使用我的证书...
    • 服务器要求您使用基本身份验证进行身份验证。这是经过编码的用户名和密码,并作为标头包含在您的 http 请求中。
    • 我将用户名和密码放在标题中,但我仍然有同样的错误:>>> print response.status, response.reason, response.msg 401 Unauthorized Date: Thu, 05 May 2011 13:43:30 GMT 服务器:Apache-Coyote/1.1 WWW-Authenticate: Basic realm="SYNCNB Server Realm" Content-Type: text/html;charset=utf-8 Content-Length: 954
    【解决方案3】:

    您正在尝试连接到需要基于客户端证书进行身份验证的 Web 服务。

    确定您有 PEM 文件而不是 PKCS#12 文件吗? PEM 文件看起来像这样(是的,我知道我包含了一个私钥……这只是我为本示例生成的一个虚拟文件):

    -----BEGIN RSA PRIVATE KEY-----                                                                     
    MIICXQIBAAKBgQDDOKpQZexZtGMqb7F1OMwdcFpcQ/pqtCoOVCGIAUxT3uP0hOw8                                    
    CZNjLT2LoG4Tdl7Cl6t66SNzMVyUeFUrk5rkfnCJ+W9RIPkht3mv5A8yespeH27x                                    
    FjGVbyQ/3DvDOp9Hc2AOPbYDUMRmVa1amawxwqAFPBp9UZ3/vfU8nxwExwIDAQAB                                    
    AoGBAMCvt3svfr9zysViBTf8XYtZD/ctqYeUWEZYR9hj36CQyVLZuAnyMaWcS7j7                                    
    GmrfVNygs0LXxoO2Xvi0ZOxj/mZ6EcZd8n37LxTo0GcWvAE4JjPr7I4MR2OvGYa/                                    
    1696e82xwEnUdpyBv9z3ebleowQ1UWP88iq40oZYukUeignRAkEA9c7MABi5OJUq                                    
    hf9gwm/IBie63wHQbB2wVgB3UuCYEa4Zd5zcvJIKz7NfhsZKKcZJ6CBVxwUd84aQ                                    
    Aue2DRwYQwJBAMtQ5yBA8howP2FDqcl9sovYR0jw7Etb9mwsRNzJwQRYYnqCC5yS                                    
    nOaNn8uHKzBcjvkNiSOEZFGKhKtSrlc9qy0CQQDfNMzMHac7uUAm85JynTyeUj9/                                    
    t88CDieMwNmZuXZ9P4HCuv86gMcueex5nt/DdVqxXYNmuL/M3lkxOiV3XBavAkAA                                    
    xow7KURDKU/0lQd+x0X5FpgfBRxBpVYpT3nrxbFAzP2DLh/RNxX2IzAq3JcjlhbN                                    
    iGmvgv/G99pNtQEJQCj5AkAJcOvGM8+Qhg2xM0yXK0M79gxgPh2KEjppwhUmKEv9                                    
    o9agBLWNU3EH9a6oOfsZZcapvUbWIw+OCx5MlxSFDamg                                                        
    -----END RSA PRIVATE KEY-----                                                                    
    -----BEGIN CERTIFICATE-----                                                                         
    MIIDfjCCAuegAwIBAgIJAOYJ/e6lsjrUMA0GCSqGSIb3DQEBBQUAMIGHMQswCQYD                                    
    VQQGEwJVUzELMAkGA1UECBMCRkwxDjAMBgNVBAcTBVRhbXBhMRQwEgYDVQQKEwtG                                    
    b29iYXIgSW5jLjEQMA4GA1UECxMHTnV0IEh1dDEXMBUGA1UEAxMOd3d3LmZvb2Jh                                    
    ci5jb20xGjAYBgkqhkiG9w0BCQEWC2Zvb0BiYXIuY29tMB4XDTExMDUwNTE0MDk0                                    
    N1oXDTEyMDUwNDE0MDk0N1owgYcxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJGTDEO                                    
    MAwGA1UEBxMFVGFtcGExFDASBgNVBAoTC0Zvb2JhciBJbmMuMRAwDgYDVQQLEwdO                                    
    dXQgSHV0MRcwFQYDVQQDEw53d3cuZm9vYmFyLmNvbTEaMBgGCSqGSIb3DQEJARYL                                    
    Zm9vQGJhci5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMM4qlBl7Fm0                                    
    YypvsXU4zB1wWlxD+mq0Kg5UIYgBTFPe4/SE7DwJk2MtPYugbhN2XsKXq3rpI3Mx                                    
    XJR4VSuTmuR+cIn5b1Eg+SG3ea/kDzJ6yl4fbvEWMZVvJD/cO8M6n0dzYA49tgNQ                                    
    xGZVrVqZrDHCoAU8Gn1Rnf+99TyfHATHAgMBAAGjge8wgewwHQYDVR0OBBYEFHZ+                                    
    CPLqn8jlT9Fmq7wy/kDSN8STMIG8BgNVHSMEgbQwgbGAFHZ+CPLqn8jlT9Fmq7wy                                    
    /kDSN8SToYGNpIGKMIGHMQswCQYDVQQGEwJVUzELMAkGA1UECBMCRkwxDjAMBgNV                                    
    BAcTBVRhbXBhMRQwEgYDVQQKEwtGb29iYXIgSW5jLjEQMA4GA1UECxMHTnV0IEh1                                    
    dDEXMBUGA1UEAxMOd3d3LmZvb2Jhci5jb20xGjAYBgkqhkiG9w0BCQEWC2Zvb0Bi                                    
    YXIuY29tggkA5gn97qWyOtQwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOB                                    
    gQAv13ewjgrIsm3Yo8tyqTUHCr/lLekWcucClaDgcHlCAH+WU8+fGY8cyLrFFRdk                                    
    4U5sD+P313Adg4VDyoocTO6enA9Vf1Ar5XMZ3l6k5yARjZNIbGO50IZfC/iblIZD                                    
    UpR2T7J/ggfq830ACfpOQF/+7K+LgFLekJ5dIRuD1KKyFg==                                                    
    -----END CERTIFICATE-----
    

    阅读this问题。

    【讨论】:

    • 嗨 A,J 是的,我确定,我的证书类似于: -----BEGIN CERTIFICATE----- blablaba -----END CERTIFICATE-----
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-09
    • 2021-04-04
    • 1970-01-01
    • 2014-11-01
    相关资源
    最近更新 更多