问题
I am trying to POST xml to a site using python. I have to include a certificate but am unsure of how to do this. Is it enough to specify the file path of the certificate locally on my computer?
Can anybody show my an example of how to include the certificate in the request?
import http.client, urllib.parse
xml="""<?xml version="1.0" encoding="UTF-8"?>
<home>
<bathroom>1</bathroom>
<kitchen>1</kitchen>
<street>515</street>
</home>);"""
headers = {"username": "password"}
conn = http.client.HTTPSConnection("someurl.com", cert_file="D:\Users\Username\certificate.p12")
conn.request("POST", "/to/this/place", xml, headers)
response = conn.getresponse()
print(response.status, response.reason)
data = response.read()
print(data)
conn.close()
回答1:
If you aren't using self-signed certs and your cert is signed by a relatively trustworthy authority (i.e. to a normal someurl.com on the internet) then you should use the system CA certificates when making your connection.
You can do that by just invoking the HTTPSConnection() without giving it a cert file or context in Python 3.4.3 or greater.
If you are using self-signed certificates then yes you can load the certs from the local hard drive. You will need to have the private key included in the certificate file or specified as the key file. You will also want to do host verification if it is at all possible in your environment. See the verify_mode
and check_hostname
options.
import http.client
import ssl
password = input("Key password (enter for none):") or None
xml = """<?xml version="1.0" encoding="UTF-8"?>
<home>
<bathroom>1</bathroom>
<kitchen>1</kitchen>
<street>515</street>
</home>);"""
headers = {"username": "password"}
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
context.load_cert_chain("cert.pem", "key.pem", password=password)
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = True
conn = http.client.HTTPSConnection("someurl.com", port=443, context=context)
conn.request("POST", "/to/this/place")
response = conn.getresponse()
print(response.status, response.reason)
data = response.read()
print(data)
conn.close()
回答2:
I used this to avoid having clients do the pkcs12 to PEM conversion. Basically override the context class to allow it to load pkcs12 files. This works with python3
import requests
from OpenSSL import crypto
class Pkcs12Context(requests.packages.urllib3.contrib.pyopenssl.OpenSSL.SSL.Context):
def __init__(self, method):
super().__init__(method)
p12 = crypto.load_pkcs12(open("/certs/client.p12", 'rb').read(), 'password')
self.use_certificate(p12.get_certificate())
self.use_privatekey(p12.get_privatekey())
# Monkey-patch the subclass into OpenSSL.SSL so it is used in place of the stock version
requests.packages.urllib3.contrib.pyopenssl.OpenSSL.SSL.Context = Pkcs12Context
r = requests.get('https://example.com')
print(r.text)
来源:https://stackoverflow.com/questions/35171751/example-of-including-a-certficate-in-a-post-request-with-python-and-http-client