Example of including a certficate in a post request with python and http.client

大兔子大兔子 提交于 2019-12-12 17:16:15

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!