使用PEM证书的HTTPS连接

psi*_*ais 8 python ssl https certificate

我正在尝试使用以下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()
Run Code Online (Sandbox Code Playgroud)

我有以下错误:

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
Run Code Online (Sandbox Code Playgroud)

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

200 ok
Run Code Online (Sandbox Code Playgroud)

当我添加身份验证标头(如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})
Run Code Online (Sandbox Code Playgroud)

我有401个未经授权的回复!

如您所见,首先,我被要求提供PrivateKey!如果我是客户,为什么我需要PrivateKey?然后,当我删除PrivateKey和证书,并把路径/正文/标题我有401 Unauthorized错误消息WWW-Authenticate:Basic realm ="SYNCNB Server Realm".

任何人都可以解释这个问题吗?是否有另一种使用Python证书发送HTTPS请求的方法?

jat*_*ism 8

听起来你需要类似我之前提供的答案来执行简单的客户端证书身份验证.以下是针对您的问题略微修改的代码:

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
Run Code Online (Sandbox Code Playgroud)

  • @jathanism你的代码丢失了一个错误.TypeError:getConnection()得到一个意外的关键字参数'timeout' (3认同)

Mat*_*ttH 2

请参阅http://docs.python.org/library/httplib.html

\n\n

httplib.HTTPSConnection不对 server\xe2\x80\x99s 证书进行任何验证。

\n\n

当服务器对客户端进行基于证书的身份验证时,可以选择包含您的私有证书。即服务器正在检查客户端是否拥有由其信任的 CA 签名的证书,并允许其访问其资源。

\n\n
\n\n

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

\n\n
\n\n

更新

\n\n

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

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