MAMP & PHP “SSL 操作失败,代码为 1”

MAMP & PHP “SSL operation failed with code 1”

编辑 我现在在路上,我的 iPhone 上的 Stack Exchange 应用程序只有 SO,所以下面代码中的引号有一些奇怪的格式 - 抱歉!我在真实代码中有真实的:)

两天来我一直在尝试解决这个问题,还有一些关于 SO 的其他问题,但是这里...

只是试图使用 file_get_contents() 捕获位于同一服务器和同一域的另一个文件的网页,并将其包含在内。我正在使用带有自签名证书的 MAMP 进行生产(这样我就可以让服务器强制使用 SSL 等)就是这样,而且我还在我的 Mac 本地拥有该证书作为“始终受信任”,因为它是自己的-签名明显。

所以现在我遇到了一个问题,我希望一个页面捕获另一个页面的内容。我最初尝试使用 cURL 但它失败了,没有给我任何例外,并且没有使用 curl_error() 的信息所以我切换到 file_get_contents() 我得到异常 SSL operation failed with code 1... ssl3_get_server_certificate:certificate verify failed

我认为这是 OpenSSL 不信任自签名的问题(但我认为它使用了底层 OS 的受信任 CA?)并且我无法使用以下命令使其工作流上下文:

stream_context_create([
   "ssl" => [
      "allow_self_signed" => true
   ]
]);

如果我将 verify_peerverify_peer_name 设置为 false,则会发出请求但不会发送 HTTPS cookie,这会破坏整个过程。

我尝试将证书的实际文本添加到 MAMP 中 OpenSSL 目录下的 cacert.pem 文件,并在 php.iniopenssl.cafile 选项中设置该文件另一个答案中所述的文件,但可惜没有运气......

有什么想法吗?非常感谢您的帮助!谢谢! ☺️

编辑 2 所以我使用 cURL 再次尝试,这次让 cURL 给我一些详细的文件输出,这就是它给我的(注意倒数第三行):

*   Trying ::1...
* TCP_NODELAY set
* Connected to admin.voyagerisc (::1) port 8890 (#0)
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /Applications/MAMP/Library/OpenSSL/certs/cacert.pem   CApath: none
* SSL certificate problem: unable to get local issuer certificate
* Curl_http_done: called premature == 1
* Closing connection 0

...这是我将原始证书添加到顶部的文件。呃,STUCK!

TLDR;你需要成为你自己的(迷你)CA,这样你就有了一个可以信任的根证书

所以经过几天的艰苦努力,我终于弄明白了这一点,我希望下面的内容能帮助那些无疑会 运行 解决这个问题的少数 MAMP / PHP 用户!!

基本上,file_get_contents()cURL 在 OpenSSL 之上运行,并且(正如我现在了解到的那样,我是 SSL 菜鸟!)OpenSSL,就像每个设备基本上都有所有主要的大列表证书颁发机构的根证书。因此,如果任何证书已由其中一个根证书签署,则在 OpenSSL 眼中可以信任。

现在您可以进入 OpenSSL 使用的具有所有大根证书的文件,我认为这就像将开发站点的原始自签名证书放在列表顶部一样简单,然后一切都会水到渠成。 但是,出于某种原因,如果它不是 ROOT CERTIFICATE.

,OpenSSL 将不会信任它

长话短说,步骤如下:

  1. 跟随 this guide 在 5 分钟内成为您自己的 CA。 (作为旁注,这现在意味着您可以 新创建的根证书,并且对于您想要使用 SSL 的每个开发站点,使用该根证书进行自签名,您就赢了不需要重新信任等)
  2. 一旦您按照文章信任根证书,并且 pointed MAMP 特定站点 的密钥和证书,在您的 IDE 打开您创建的 ROOT CERTIFICATE 的 .pem 文件,而不是您的开发站点的特定文件
  3. 对于 MAMP,OpenSSL 用作受信任证书颁发机构核心列表的文件位于 /Applications/MAMP/Library/OpenSSL/certs/ - 在您的 IDE 中也打开 cacert.pem
  4. 现在,在第一个真正的 CA 之前的评论下,复制并粘贴您的根证书的原始数据。您还可以在该长数据之前(以及 BEFORE -----BEGIN CERTIFICATE----- 行)添加您在第 1 步中为证书颁发机构设置的名称,并将其格式化为= 与其他证书颁发机构一样。
  5. 通常:保存并重启 MAMP

现在,如果您运行使用 MAMP 连接本地开发服务器并启用了自签名 SSL,您现在应该能够将 SSL 调用返回到服务器本身,并拥有服务器信任....本身?我猜?想想就觉得奇怪!

最后一点,如果您在 SO 上访问过任何其他类似问题,您会看到许多答案提示您使用 get_file_contents() 创建流上下文或使用 cURL 资源建议在流上下文中转换 "verify_peer" => false"verify_peer_name" => false,或 cURL 的等效选项。我 怎么强调都不够 该方法完全违背了 SSL 的目的,甚至不应该用于本地开发,因为您可能会忘记将其重新打开或其他一些晦涩难懂的东西导致信任在生产中保持关闭的事件。

我上面描述的方法更乏味,是的,但它会帮助你完成开发,直到你拥有一个真正的 CA 签署的真正的生产 SSL 证书,到那时这甚至不再是问题.

如果这个解释不够清楚/准确,请随时发表评论,我只是还在摸索!干杯:)

正如 Mike 提到的(见评论),在当前版本的 MAMP (6.4) 中,/Applications/MAMP/Library/OpenSSL/certs/cacert.pem 添加了一个无效的证书文件。只需打开此文件并访问 301 重定向 (https://curl.se/ca/cacert.pem) 中显示的 link,下载它并替换文件。