HTTPS接口测试翻车实录:为什么浏览器能访问而curl报证书错误?
最近在项目里遇到一个挺有意思的坑,我们团队新开发了一个HTTPS接口,内部测试时用浏览器访问一切正常,Postman调一下也没问题,结果交付给第三方调用时,对方直接用curl命令测试,直接抛出一个Peer's Certificate issuer is not recognized的错误,接口直接“挂掉”。这场景估计不少后端和API开发者都遇到过——明明自己这边好好的,怎么到了别人那儿就出问题?今天我就结合这次踩坑经历,聊聊这背后的技术细节,特别是浏览器、Postman和curl这三者在处理SSL/TLS证书时的“性格差异”。
很多人第一反应是证书配置错了,比如证书链不完整、根证书不受信任或者证书过期。这确实是常见原因,但如果你已经反复确认证书本身没问题(比如用openssl验证过证书链是完整的),那么问题可能出在更隐蔽的环节:协议协商或代理转发过程中,HTTPS请求被“降级”处理了。简单说,就是客户端以为自己在进行安全的HTTPS通信,但请求到达真正的服务端时,却变成了明文的HTTP。服务端自然无法提供对应的SSL证书,客户端(如curl)在SSL握手阶段收不到预期的证书,就会报出各种证书相关的错误,Peer's Certificate issuer is not recognized只是其中一种表现形式。
这篇文章我会从实际排查过程出发,对比不同工具的行为,并用Wireshark抓包带你直观看到协议层面的差异。无论你是负责API交付的开发,还是需要集成第三方服务的工程师,理解这些底层机制都能帮你更快定位那些“时好时坏”的网络问题。
1. 问题重现与初步排查:工具行为的“多面性”
当第三方反馈curl报错时,我的第一反应是检查证书。我们的服务部署在Nginx后面,证书是由合规的公共CA签发的,在浏览器里显示小绿锁,openssl s_client -connect命令连接也能看到完整的证书链。那为什么curl就不认呢?
1.1 三种工具的测试结果对比
我首先在本地用三种方式测试了同一个HTTPS接口:
浏览器(Chrome): 直接输入https://api.example.com/v1/test,页面正常加载,返回预期JSON数据。开发者工具Network标签页显示协议为h2(HTTP/2 over TLS),状态码200,没有任何安全警告。
Postman: 这里有个关键细节。Postman的SSL证书验证设置默认是开启的,但它的行为比curl“灵活”一些。
- 在默认设置下,直接发送请求,有时成功,有时失败。失败时的错误信息与
curl类似。 - 如果进入Settings,将“SSL certificate verification”选项关闭,则请求100%成功。
cURL命令: 在终端执行最简单的GET请求:
curl https://api.example.com/v1/test
立刻返回错误:
curl: (60) Peer‘s Certificate issuer is not recognized
More details here: https://curl.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to


1983

被折叠的 条评论
为什么被折叠?



