是否可以使用流上下文在PHP下使用FTPS?

Fra*_*cke 6 php security ftp ssl ftps

我了解到在PHP for Windows下使用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
Run Code Online (Sandbox Code Playgroud)

但是,这对ftp连接有用吗?我还可以使用经过对等验证的流上下文来打开ftps流吗? php手册提示,ssl上下文选项也适用于sftp,但缺乏进一步的指导.

所以我疯狂地猜测:

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

对?错误?用户+密码现在作为选项?然后什么?用户/密码呢?还是以后?我无能为力......

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

这有甚么可能吗?(几行代码将非常有用....)或者流是否仅适用于单一文件访问?

更新:Curl可能会做我想要的(包括对等验证和目录lsiting),如本SO答案所示.本周晚些时候会检查......

rdl*_*rey 14

这会有用吗?

我还可以使用经过对等验证的流上下文来打开ftps流吗?

是.该FTPS流封装采用相同的SSL上下文选项为HTTPS包装,将可只要你有你的PHP构建支持OpenSSL的扩展.您可以通过检查输出来验证ftps包装器是否可用stream_get_wrappers():

<?php
print_r(stream_get_wrappers());
Run Code Online (Sandbox Code Playgroud)

如果您在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'
]]);
Run Code Online (Sandbox Code Playgroud)

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

我在哪里放置用户名/密码?

对?错误?用户+密码现在作为选项?然后什么?用户/密码呢?还是以后?我无能为力......

FTPFTPS流包装都期望在URI的用户名和密码,如下所示:

<?php
$ftpPath = 'ftps://username:password@example.com';
Run Code Online (Sandbox Code Playgroud)

不要被我们的用户规范/通过明文中的传递抛弃.流包装器将仅建立加密连接发送用户名和密码.

把它们放在一起

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);
Run Code Online (Sandbox Code Playgroud)

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

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

  • ✰ 大智慧直达源头!太感谢了!其中一些内容应该在 php 文档中更加直言不讳......(特别是对于那些绝望地运行“ftp_ssl_connect()”的人) (2认同)