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) w开发者_如何学Pythonith 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?
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:
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
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:
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()
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):
-----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-----
Read this question.
精彩评论