Đang cố gắng nhận chứng chỉ SSL từ phản hồi trong requests
.Cách nhận chứng chỉ SSL phản hồi từ các yêu cầu trong python?
Cách tốt nhất để làm điều này là gì?
Cảm ơn rất nhiều!
Đang cố gắng nhận chứng chỉ SSL từ phản hồi trong requests
.Cách nhận chứng chỉ SSL phản hồi từ các yêu cầu trong python?
Cách tốt nhất để làm điều này là gì?
Cảm ơn rất nhiều!
requests
cố tình kết thúc tốt đẹp thứ cấp thấp như thế này. Thông thường, điều duy nhất bạn muốn làm là verify that the certs are valid. Để làm điều đó, chỉ cần vượt qua verify=True
. Nếu bạn muốn sử dụng một gói cacert không chuẩn, bạn cũng có thể truyền nó. Ví dụ:
resp = requests.get('https://example.com', verify=True, cert=['/path/to/my/ca.crt'])
Ngoài ra, requests
chủ yếu là một bộ các hàm bao quanh các thư viện khác, chủ yếu là urllib3
và của stdlib http.client
(hoặc, đối với 2.x, httplib
) và ssl
.
Đôi khi, câu trả lời chỉ là nhận được ở các đối tượng cấp thấp hơn (ví dụ: resp.raw
là urllib3.response.HTTPResponse
), nhưng trong nhiều trường hợp không thể.
Và đây là một trong những trường hợp đó. Các đối tượng duy nhất từng thấy certs là http.client.HTTPSConnection
(hoặc urllib3.connectionpool.VerifiedHTTPSConnection
, nhưng đó chỉ là một phân lớp của trước đây) và một số ssl.SSLSocket
và không tồn tại trong số đó nữa vào thời điểm yêu cầu trả về. (Như tên connectionpool
ngụ ý, đối tượng HTTPSConnection
được lưu trữ trong một hồ bơi, và có thể được tái sử dụng càng sớm càng hoàn thành công việc; các SSLSocket
là một thành viên của HTTPSConnection
.)
Vì vậy, bạn cần phải vá thứ để bạn có thể sao chép dữ liệu lên chuỗi. Nó có thể đơn giản như thế này:
HTTPResponse = requests.packages.urllib3.response.HTTPResponse
orig_HTTPResponse__init__ = HTTPResponse.__init__
def new_HTTPResponse__init__(self, *args, **kwargs):
orig_HTTPResponse__init__(self, *args, **kwargs)
try:
self.peercert = self._connection.sock.getpeercert()
except AttributeError:
pass
HTTPResponse.__init__ = new_HTTPResponse__init__
HTTPAdapter = requests.adapters.HTTPAdapter
orig_HTTPAdapter_build_response = HTTPAdapter.build_response
def new_HTTPAdapter_build_response(self, request, resp):
response = orig_HTTPAdapter_build_response(self, request, resp)
try:
response.peercert = resp.peercert
except AttributeError:
pass
return response
HTTPAdapter.build_response = new_HTTPAdapter_build_response
Đó là chưa được kiểm tra, vì vậy không đảm bảo; bạn có thể cần phải vá nhiều hơn thế.
Ngoài ra, phân lớp và ghi đè có thể sẽ sạch hơn so với bắt chước (đặc biệt là từ HTTPAdapter
được thiết kế để được phân lớp).
Hoặc, thậm chí tốt hơn, giả mạo urllib3
và requests
, sửa đổi ngã ba của bạn và (nếu bạn cho rằng điều này là hữu ích hợp pháp), hãy gửi yêu cầu kéo ngược dòng.
Dù sao, bây giờ, từ mã của bạn, bạn có thể làm điều này:
resp.peercert
Tất nhiên bạn cũng có thể muốn vượt qua cùng tất cả các thông tin cần thiết để xác minh các CERT, nhưng điều đó thậm chí còn dễ dàng hơn, bởi vì nó đã đi qua cấp cao nhất.
này, mặc dù không đẹp chút nào, hoạt động:
import requests
req = requests.get('https://httpbin.org')
pool = req.connection.poolmanager.connection_from_url('https://httpbin.org')
conn = pool.pool.get()
# get() removes it from the pool, so put it back in
pool.pool.put(conn)
print(conn.sock.getpeercert())
Điều này chỉ hoạt động nếu kết nối vẫn còn hoạt động, điều này không được đảm bảo. Ví dụ, nếu phía bên kia gửi một 'Connection: close'. Hoặc nếu bạn đã gửi các yêu cầu khác (đặc biệt nếu bạn đang sử dụng điều này trong ngữ cảnh không đồng bộ hoặc luồng). Hoặc nếu 'urllib3' chỉ cảm thấy như nó không có lý do rõ ràng. – abarnert
Để bắt đầu, abarnert's answer là rất đầy đủ
Nhưng tôi muốn thêm, rằng trong trường hợp bạn đang tìm kiếm các chuỗi cert bạn bè, bạn sẽ cần phải vá thêm một đoạn mã
import requests
sock_requests = requests.packages.urllib3.contrib.pyopenssl.WrappedSocket
def new_getpeercertchain(self,*args, **kwargs):
x509 = self.connection.get_peer_cert_chain()
return x509
sock_requests.getpeercertchain = new_getpeercertchain
sau đó bạn có thể gọi nó là một cách rất tương tự như câu trả lời chấp nhận
HTTPResponse = requests.packages.urllib3.response.HTTPResponse
orig_HTTPResponse__init__ = HTTPResponse.__init__
def new_HTTPResponse__init__(self, *args, **kwargs):
orig_HTTPResponse__init__(self, *args, **kwargs)
try:
self.peercertchain = self._connection.sock.getpeercertchain()
except AttributeError:
pass
HTTPResponse.__init__ = new_HTTPResponse__init__
HTTPAdapter = requests.adapters.HTTPAdapter
orig_HTTPAdapter_build_response = HTTPAdapter.build_response
def new_HTTPAdapter_build_response(self, request, resp):
response = orig_HTTPAdapter_build_response(self, request, resp)
try:
response.peercertchain = resp.peercertchain
except AttributeError:
pass
return response
HTTPAdapter.build_response = new_HTTPAdapter_build_response
bạn sẽ nhận được resp.peercertchain
chứa một tuple
của OpenSSL.crypto.X509
đối tượng
Ồ, điều này rất hoàn chỉnh. Cảm ơn rất nhiều! Tôi sẽ làm việc trên nó và xem nó như thế nào. Cảm ơn một lần nữa! –