使用 PEM 证书的 HTTPS 连接
我正在尝试使用 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
当我添加带有空的 Authentication 标头(如 MattH 建议的)时发布有效负载,它也可以工作。
然而,当我用路径、正文和标题提出良好的请求时,如下所示(我简化了它们......)
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 未经授权的响应!
正如您所看到的,首先,我被要求提供 PrivateKey !如果我是客户,为什么需要私钥?然后,当我删除 PrivateKey 和证书并放置 Path/Body/headers 时,出现 401 Unauthorized 错误,并显示消息 WWW-Authenticate: Basic Realm="SYNCNB Server Realm"。
有谁能解释一下这个问题吗?还有另一种方法可以在Python中使用证书发送HTTPS请求吗?
I'm trying to POST HTTPS requests using a PEM certificate like following:
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()
I have the following error:
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
When I remove the cert_file from httplib, I've the following response:
200 ok
When I add the Authentication header (like advised by MattH) with empty post payload, it works also.
However, when I put the good request with the Path, the Body and the Header, like following (I simplified them...)
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})
I have 401 Unauthorized response !
As you can see, first, I'm asked to provide the PrivateKey ! why did I need the PrivateKey if I'm a client ? then, when I remove the PrivateKey and the certificate, and put the Path/Body/headers I have 401 Unauthorized error with the message WWW-Authenticate: Basic realm="SYNCNB Server Realm".
Could any one explain this issue? Is there another way to send HTTPS request using a certificate in Python?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
听起来您需要类似于我之前提供的答案来执行 简单的客户端证书身份验证。为了方便起见,以下是针对您的问题稍作修改的代码:
It sounds like you need something similar to an answer I have provided before to perform simple client certificate authentication. Here is the code for convenience modified slightly for your question:
请参阅 http://docs.python.org/library/httplib.html
httplib.HTTPSConnection
不对服务器的证书进行任何验证。当服务器对客户端进行基于证书的身份验证时,可以选择包含您的私有证书。即服务器正在检查客户端是否拥有由其信任的 CA 签名的证书,并允许其访问其资源。
如果不指定 cert 可选参数,您应该能够连接到 HTTPS 服务器,但无法验证服务器证书。
更新
根据您已尝试基本身份验证的评论,看起来服务器仍然希望您使用基本身份验证进行身份验证。您的凭据无效(您是否独立验证过它们?)或者您的
Authenticate
标头格式不正确。修改示例代码以包含基本身份验证标头和空的帖子有效负载:See http://docs.python.org/library/httplib.html
httplib.HTTPSConnection
does not do any verification of the server’s certificate.The option to include your private certificate is when the server is doing certificate based authentication of clients. I.e. the server is checking the client has a certificate signed by a CA that it trusts and is allowed to access it's resources.
If you don't specify the cert optional argument, you should be able to connect to the HTTPS server, but not validate the server certificate.
Update
Following your comment that you've tried basic auth, it looks like the server still wants you to authenticate using basic auth. Either your credentials are invalid (have you independently verified them?) or your
Authenticate
header isn't formatted correctly. Modifying your example code to include a basic auth header and an empty post payload:您正在做的是尝试连接到需要基于客户端证书进行身份验证的 Web 服务。
您确定您有 PEM 文件而不是 PKCS#12 文件吗? PEM 文件如下所示(是的,我知道我包含了私钥...这只是我为本示例生成的虚拟文件):
阅读 这个问题。
What you're doing is trying to connect to a Web service that requires authentication based on client certificate.
Are you sure you have a PEM file and not a PKCS#12 file? A PEM file looks like this (yes, I know I included a private key...this is just a dummy that I generated for this example):
Read this question.