能否使用流上下文在PHP中处理FTPS?

8
我了解到在Windows下使用PHP的ftps (´ftp_ssl_connect()´)很困难。你需要进行漫长的二进制文件构建来包含Open SSL... 我发现了一个替代品phpseclib的建议(但是让openssl.cnf正确支持对等验证对我来说似乎也很难...)。
然后我看到了这篇文章,它的简单示例和工作中的对等验证(避免中间人攻击)引起了我的注意,使我关注流:
$uri = 'https://www.bankofamerica.com/';
$ctx = stream_context_create(['ssl' => [
    'verify_peer' => true, // important
    'cafile' => '/hard/path/to/cacert.pem',
    'CN_match' => 'www.bankofamerica.com'
]]);
$html = file_get_contents($uri, FALSE, $ctx); // we are good

然而,这对ftp连接有用吗?我是否也可以使用peer-validated流上下文来打开ftps流?PHP手册中提到,SSL上下文选项同样适用于SFTP,但缺乏进一步的指导。

因此,我猜测:

$ctx = stream_context_create(['ftps' => [
    'verify_peer' => true,
    'cafile' => 'd:/sandbox/mycerts.pem',
    'CN_match' => 'ftp-12345678.mywebhoster.com'
]]);

对吗?错吗?现在选项是用户+密码?然后呢?现在是用户/密码?还是以后?我一无所知...

  • 我该如何扫描远程ftp目录内容?
  • 我该如何从ftp服务器上传或下载文件?

这些是否都可能?(几行代码会非常有帮助...)或者流只适用于单个文件访问?

更新: Curl可能会做我想要的事情(包括对等验证和目录列表)如此在这个SO答案中所示。将在本周晚些时候检查...

1个回答

16
这个能行吗?
可以。ftps流包装器使用与https包装器相同的SSL上下文选项,并且只要您在PHP构建中启用了openssl扩展,它就可用。您可以通过检查stream_get_wrappers()的输出来验证ftps包装器是否可用。
<?php
print_r(stream_get_wrappers());

如果您在PHP构建中启用了ext/openssl,您将在输出中看到ftps与其他可用的流包装器一起列出。

如何分配SSL上下文选项?

所以我猜测

您非常接近了!您在代码中唯一需要更改的是将"ftps"替换为"ssl",如下所示:

<?php
$ctx = stream_context_create(['ssl' => [
    'verify_peer' => true,
    'cafile' => 'd:/sandbox/mycerts.pem',
    'CN_match' => 'ftp-12345678.mywebhoster.com'
]]);

无论您使用的是 httpsftps 还是其他任何流包装器,控制 SSL/TLS 加密的上下文选项始终存储在 "ssl" 键中。

用户/密码应该放在哪里?

对吗?错吗?现在将用户+密码作为选项?然后呢?现在是用户/密码吗?还是以后?我一头雾水...

ftpftps 流包装器都希望在 URI 中提供用户名和密码,如下所示:

<?php
$ftpPath = 'ftps://username:password@example.com';

不要被我们在这里以明文指定用户/密码所迷惑。流包装器只会在建立加密连接之后发送用户名和密码。
将所有内容整合在一起 opendir()函数族支持ftp包装器(自PHP 5.0起)。您可以像处理本地文件系统路径一样使用这些函数:
<?php
$ctx = stream_context_create(['ssl' => [
    'verify_peer' => true,
    'cafile' => 'd:/sandbox/mycerts.pem',
    'CN_match' => 'ftp-12345678.mywebhoster.com'
]]);
$dirHandle = opendir('ftps://username:password@example.com/', $ctx);
while (($file = readdir($dirHandle)) !== false) {
    echo "filename: $file\n";
}
closedir($dirHandle);

关于SSL/TLS名称匹配的注意事项

如果一开始无法正常工作,您应该尝试不传递包含SSL选项的附加上下文$ctx进行测试。服务器证书的CN(通用名称)字段必须与您指定的"CN_match"值匹配(对于子域名有限通配符匹配)。此外,在即将发布的PHP-5.6版本之前,不支持将名称与远程方证书中的主题备用名称字段进行匹配。除非您使用的是5.6的开发预览版,否则您将无法使用此功能(SAN匹配),并且如果服务器依赖于SAN,对等验证过程将失败。


2
✰ 来自源头的伟大智慧!非常感谢!其中一些内容应该更加直言不讳地写入 PHP 文档中...(特别是那些将绝望地运行 ftp_ssl_connect() 的人们)。 - Frank N
1
@Fronker 很高兴我能帮到你 :) 是的,我现在到5.6发布之间有很多文档更新要做。 - user895378

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接