【问题标题】:PEM Certificate & TLS Verification against REST api针对 REST api 的 PEM 证书和 TLS 验证
【发布时间】:2021-12-28 16:44:04
【问题描述】:

我已获得一个 pem 证书,用于向第三方进行身份验证。使用证书进行身份验证对我来说是一个新概念。

里面有两个证书和一个私钥。

发行人已告知他们不支持 SSL 验证,但使用 TLS(1.1/1.2)。

我已经运行了如下脚本:

import requests as req
import json

url = 'https://url.com/call'
certificate_file = "C:/certs/cert.pem"

headers = {"Content-Type": "application/json"}
 
req_body ={
    "network":{
                "network_id": 12345
    },
    "branch":{
                "branch_id": 12345,
    },
  "export_period":{
        "start_date_time": "16-11-2021 00:00:00",
        "end_date_time": "17-11-2021 00:00:00"
    }
}
 
jsonObject = json.dumps(req_body)
response = req.post(url,headers=headers,params=jsonObject,verify=certificate_file)

我收到以下错误:

SSLError: HTTPSConnectionPool(host='url.com, port=443): 最大重试次数超出 url: /call?%7B%22network%22:%20%7B%22network_id%22:%2012345%7D,% 20%22branch%22:%20%7B%22branch_id%22:%2012345%7D,%20%22export_period%22:%20%7B%22start_date_time%22:%20%2216-11-2021%2000:00:00 %22,%20%22end_date_time%22:%20%2217-11-2021%2000:00:00%22%7D%7D (由 SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] 证书验证失败: 无法获取本地颁发者证书 (_ssl.c:1123)')))

不胜感激,我的直觉说我应该针对 TLS 做一些特定的事情,因此会出现 SSL 错误。

【问题讨论】:

  • 我认为你不需要对 TLS 做任何事情,这通常会在连接建立时被拾取。相反,它似乎位于证书中的某个位置(不正确或自签名且未验证),或者您缺少链中的中间证书。或者,您的 CA(证书颁发机构)列表可能不完整。我从未在 python 中使用过它,但显然有办法更新它(参见:stackoverflow.com/questions/51925384/…
  • 另外,不使用 SSL 验证会有很大的风险。如果这确实是“解决方案”,那么您只需在帖子中声明“verify=False”即可。
  • 请您显示两个证书的主题和颁发者哈希:openssl x509 -in <filename> -noout -subject_hash-issuer_hash 类似。这将有助于显示它们之间的关系。

标签: python rest python-requests


【解决方案1】:

发行人正在使用最新版本的 HTTPS - SSL 是常用术语,但 TLS 是更正确的术语。听起来他们的设置是正确的 - 这意味着您需要使用受信任的客户端证书调用它,作为 HTTPS 请求的一部分。

我建议先使用 curl 工具执行此操作,以便您可以验证 API 是否按预期工作。

curl -s -X GET "https://api.example.com/test" \
--cert ./certs/example.client.pem \
--key ./certs/example.client.key \
--cacert ./certs/ca.pem \
-H "Content-Type: application/json"

如上所述将证书拆分为单独的文件。听起来其中之一是您需要告诉客户端技术堆栈信任的根证书颁发机构 - 对于 curl,这是使用上面的 cacert 参数完成的。

一旦此方法生效,您就可以在 Python 请求库中采用相同的方法。我相信这使用了certverify 这样的参数。所以看起来你的代码离我们不远了。

result = requests.get(
    'https://api.example.com',
    cert=('example.pem', 'example.key'),
    verify='ca.pem')

关于双向 TLS 的更多信息

出于兴趣,如果您想揭开 Mutual TLS 的神秘面纱并了解更多信息,请查看以下 Curity 高级资源:

其中包括您可以运行的OpenSSL Script,以查看分离的证书文件应该是什么样子。

【讨论】:

  • 非常感谢 - 会试一试并报告。
【解决方案2】:

发行人已告知他们不支持 SSL 验证

对我来说,这听起来很冒险,但如果确实如此,那么简单

verify=False

应该可以解决问题。注意:这会完全禁用此调用的 SSL 证书验证。

此外,如果您仍然需要 SSL 证书(从我的评论中复制粘贴):

我认为您不需要对 TLS 做任何事情,这通常会在连接建立时被拾取。相反,它似乎位于证书中的某个位置(不正确或自签名且未验证),或者您缺少链中的中间证书。或者,您的 CA(证书颁发机构)列表可能不完整。我从未在 python 中使用过它,但显然有办法使用 certifi 来更新它。可以在in this relevant SO question找到这方面的文档。

【讨论】:

  • 不确定veryify-false 会不会删减它?我仍然需要使用证书进行身份验证。
【解决方案3】:

我找到了带有答案的similar question。看起来系统安全库可能无法在链中找到证书,因为“只有存储在 cacert.pem 中的证书链才被认为是有效的。”

【讨论】:

    猜你喜欢
    • 2017-10-07
    • 2021-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-27
    • 1970-01-01
    相关资源
    最近更新 更多