【发布时间】:2019-06-05 14:36:05
【问题描述】:
我有使用自签名证书的 Python 编写的 https 服务器:
server_cert = 'certs/server/server.crt'
server_key = 'certs/server/server.key'
client_certs = 'certs/client/client.crt'
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.verify_mode = ssl.CERT_REQUIRED
context.load_cert_chain(certfile=server_cert, keyfile=server_key)
context.load_verify_locations(cafile=client_certs)
生成证书的步骤:
openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=localhost/UID=testnotifier" -keyout ${certs}/server/server.key -out ${certs}/server/server.crt
openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=localhost/UID=testnotifier" -keyout ${certs}/client/client.key -out ${certs}/client/client.crt
我还有 https 客户端:
#!/usr/bin/python3
import socket
import ssl
host_addr = '127.0.0.1'
host_port = 8082
server_sni_hostname = 'localhost'
server_cert = 'certs/server/server.crt'
client_cert = 'certs/client/client.crt'
client_key = 'certs/client/client.key'
context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH, cafile=server_cert)
context.load_cert_chain(certfile=client_cert, keyfile=client_key)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn = context.wrap_socket(s, server_side=False, server_hostname=server_sni_hostname)
conn.connect((host_addr, host_port))
conn.send(b"Hello, world!")
conn.close()
这可行,但我想向某个路径发送不同的请求,例如/rest/v1/fill。
所以,我决定使用requests 或urllib3 lib。
我正在尝试将证书传递给这个库
https = urllib3.PoolManager(cert_file=client_cert, cert_reqs='CERT_REQUIRED', ca_certs=server_cert, key_file=client_key)
https.request('GET', 'https://localhost:8082/rest/v1/fill')
但客户端与两个库一起挂起:
/home/marat/.local/lib/python3.6/site-packages/urllib3/connection.py:362: SubjectAltNameWarning: Certificate for localhost has no `subjectAltName`, falling back to check for a `commonName` for now. This feature is being removed by major browsers and deprecated by RFC 2818. (See https://github.com/shazow/urllib3/issues/497 for details.)
SubjectAltNameWarning
^CTraceback (most recent call last):
File "/home/marat/.local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 377, in _make_request
httplib_response = conn.getresponse(buffering=True)
TypeError: getresponse() got an unexpected keyword argument 'buffering'
服务器的输出:
Client connected: 127.0.0.1:40026
SSL established. Peer: {'subject': ((('countryName', 'US'),), (('stateOrProvinceName', 'Denial'),), (('localityName', 'Springfield'),), (('organizationName', 'Dis'),), (('commonName', 'localhost'),), (('userId', 'testnotifier'),)), 'issuer': ((('countryName', 'US'),), (('stateOrProvinceName', 'Denial'),), (('localityName', 'Springfield'),), (('organizationName', 'Dis'),), (('commonName', 'localhost'),), (('userId', 'testnotifier'),)), 'version': 3, 'serialNumber': '88F15B15B2D1ABE7', 'notBefore': 'Jun 5 11:35:38 2019 GMT', 'notAfter': 'Jun 4 11:35:38 2020 GMT'}
Received: b'GET / HTTP/1.1\r\nHost: localhost:8082\r\nAccept-Encoding: identity\r\n\r\n'
Closing connection
我想知道如何传递证书,以便客户端像第一个版本一样工作(使用socket/ssl)。
【问题讨论】:
标签: python-3.x https openssl