Python 使用PEM证书的HTTPS连接
我尝试使用PEM证书发布HTTPS请求,如下所示:Python 使用PEM证书的HTTPS连接,python,ssl,https,certificate,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.rea
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
当我添加带有空post负载的身份验证头(如MattH建议的)时,它也可以工作
然而,当我将好的请求与路径、主体和头放在一起时,就像下面(我简化了它们…)
body='blabla'
URLprov=“/syncaxis2/services/XXXsyncService”
auth_头='Basic%s'(“:”).join([“xxx”,“xxxxx”).encode('Base64').strip('\r\n'))
conn.request(“POST”、URLprov、body、{'Authenticate':auth_header})
我有401个未经授权的响应
如你所见,首先,我被要求提供私钥!如果我是客户,为什么我需要私钥?然后,当我删除私钥和证书,并放置路径/正文/标题时,我有401个未经授权的错误,消息为WWW-Authenticate:Basic-realm=“SYNCNB-Server-realm”
有人能解释这个问题吗?是否有其他方法可以使用Python中的证书发送HTTPS请求?请参阅
httplib.HTTPSConnection
不验证服务器的证书
当服务器对客户端执行基于证书的身份验证时,可以选择包含您的私有证书。也就是说,服务器正在检查客户机是否拥有由其信任的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()
您正在尝试连接到需要基于客户端证书进行身份验证的Web服务 您是否确定您有PEM文件而不是PKCS#12文件?PEM文件如下所示(是的,我知道我包含了一个私钥……这只是我为本例生成的一个伪文件):
阅读问题。听起来你需要类似于我之前提供的答案的东西来执行。以下是为方便起见针对您的问题稍微修改的代码:
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
嗨,MattH,事实上,当我没有指定cert可选参数时,我得到的响应是。。。您能告诉我如何验证我的证书以便被远程服务器接受吗?非常感谢你的邀请help@psikais:该服务需要某种形式的身份验证。查看服务器401响应中的“WWW-Authenticate”标题,了解其支持的身份验证方案的详细信息。@MattH,我收到了错误消息“WWW-Authenticate:Basic realm=“SYNCNB-server-realm”“。此外,正如我告诉您的,我没有在任何地方使用我的证书…服务器要求您使用基本身份验证进行身份验证。这是一个用户名和密码编码并包含在http请求的标题中。我将用户和密码放在标题中,但仍有相同的错误:>>>print response.status,response.reason,response.msg 401未经授权日期:2011年5月5日星期四13:43:30 GMT服务器:Apache Coyote/1.1 WWW Authenticate:Basic realm=“SYNCNB服务器域”内容类型:text/html;charset=utf-8内容长度:954Hi A,J是的,我确定,我的证书类似于:-开始证书------Blablablaba------结束证书------Hi jathanism,事实上,我只有client_cert_file.pem(base64文件)因为我是将连接到服务器的客户端,我想使用它向服务器发送HTTPS请求。也许我没有使用使用SSL PEM证书询问服务器的好方法?@jathanism您的代码出现错误。TypeError:getConnection()得到了一个意外的关键字参数“timeout”,您可以通过将行更改为
getConnection(self,host,timeout=300)来修复它:
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()
-----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-----
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