使用 PHP 和私钥连接到 SFTP


Connect to SFTP using PHP and private key

我读了一篇文章又一篇文章,只是找不到适合我所拥有的"解决方案"。

我正在尝试使用 php 脚本通过 SFTP 上传文件。我已经使用 CyberDuck 成功连接,但我需要以编程方式执行此操作。

我有一个.PPK 文件来自我在 CyberDuck 中使用的供应商。我有一个用户名。我有主机名。如果我打开PPK文件,我会看到一些公共线路,专用线路和专用MAC。

无论如何,我

可以访问服务器以使用我拥有的信息执行我需要做的事情吗?

这是我正在使用的代码:

<?php if (!function_exists("ssh2_connect")) die("function ssh2_connect doesn't exist");
?>
<?php
$conn = ssh2_connect('hostname.com', 22);
echo $conn;
ssh2_auth_pubkey_file($conn,'USERNAME','/var/www/html/FILENAME.PPK');
// send a file
ssh2_scp_send($conn, '/var/www/html/FILETOSEND.TXT', 'FILETOSEND.TXT', 0644);
?>

我没有收到任何错误,但该文件未显示在服务器上。我可以确认SSH2已安装在我的虚拟主机上。

感谢您提供的任何帮助。

这个问题很老了,但是由于我正在寻找完全相同的答案,这是我设法收集到的。

首先:将密钥格式从 .ppk 更改为 .pem

.pkk密钥是PuTTY格式的私钥。

如果要将其更改为 .pem 格式,则需要安装带有以下内容的腻子工具:

sudo apt install putty-tools

(在 Mac 上,使用自制软件安装腻子包。对于Windows,我不知道。

然后,您可以更改密钥的格式:

puttygen privatekey.ppk -O private-openssh -o privatekey.pem
以防万

一您想从该私钥中提取公钥(您不需要该答案的其余部分,但以防万一)这很容易:

openssl rsa -in privatekey.pem -pubout > publickey.pub

第二:使用sFTP登录

现在你已经有了privatekey.pem,你可以使用 phpseclib 通过 SFTP 进行连接。首先,使用 Composer 安装 phpseclib:

composer require phpseclib/phpseclib

然后在 PHP 中:

require "vendor/autoload.php";
use phpseclib'Crypt'RSA;
use phpseclib'Net'SFTP;
$sftp = new SFTP('sftp.server.com');
// create new RSA key
$privateKey = new RSA();
// in case that key has a password
$privateKey->setPassword('private key password');
// load the private key
$privateKey->loadKey(file_get_contents('/path/to/privatekey.pem'));
// login via sftp
if (!$sftp->login('username', $privateKey)) {
    throw new Exception('sFTP login failed');
}
// now you can list what's in here
$filesAndFolders = $sftp->nlist();
// you can change directory
$sftp->chdir('coolstuffdir');
// get a file
$sftp->get('remoteFile', 'localFile');
// create a remote new file with defined content
$sftp->put('newfile.txt', 'new file content');
// put a local file
$sftp->put('remote.txt', 'local.txt', NET_SFTP_LOCAL_FILE);

如果您想了解更多信息,请转到phpseclib sFTP功能列表。

如果我可以根据Stéphane Le Solliec回答的代码示例分享我的发现,你们必须检查你们的phpseclib版本。 要通过作曲家(Windows)检查phpseclib版本,您只需在命令提示符composer require phpseclib/phpseclib中输入,结果将显示安装的版本。

如果 phpseclib 版本是 1.0,我建议你将行$sftp = new SFTP('sftp.server.com');修改为$sftp = new NET_SFTP('sftp.server.com');

如果 phpseclib 版本是 2.0,我建议你将行$sftp->put('remote.txt', 'local.txt', NET_SFTP_LOCAL_FILE);修改为 $sftp->put('remote.txt', 'local.txt', SFTP::SOURCE_LOCAL_FILE);

谢谢。

您可以使用 Flysystem sftp 适配器进行 php。您可以在使用作曲家安装的任何框架中使用它。Flysystem Filesystem Abstraction for PHP (PHP library)。

https://flysystem.thephpleague.com/v2/docs/

使用命令安装库。

composer require league/flysystem-sftp:^2.0

使用以下代码通过文件系统与 SFTP 连接。

<?php
require_once('vendor/autoload.php');
use League'Flysystem'Filesystem;
use League'Flysystem'PhpseclibV2'SftpConnectionProvider;
use League'Flysystem'PhpseclibV2'SftpAdapter;
use League'Flysystem'UnixVisibility'PortableVisibilityConverter;
use League'Flysystem'DirectoryAttributes;
use League'Flysystem'FileAttributes;
$private_key='sftp_keys/new_private.ppk';
$filesystem = new Filesystem(new SftpAdapter(
    new SftpConnectionProvider(
        'host', // host (required)
        'username', // username (required)
        null, // password (optional, default: null) set to null if privateKey is used
        $private_key, // private key (optional, default: null) can be used instead of password, set to null if password is set
        null, // passphrase (optional, default: null), set to null if privateKey is not used or has no passphrase
        22, // port (optional, default: 22)
        false, // use agent (optional, default: false)
        30, // timeout (optional, default: 10)
        10, // max tries (optional, default: 4)
        null, // host fingerprint (optional, default: null),
        null // connectivity checker (must be an implementation of 'League'Flysystem'PhpseclibV2'ConnectivityChecker' to check if a connection can be established (optional, omit if you don't need some special handling for setting reliable connections)
    ),
    '/', // root path (required)
    PortableVisibilityConverter::fromArray([
        'file' => [
            'public' => 0640,
            'private' => 0604,
        ],
        'dir' => [
            'public' => 0740,
            'private' => 7604,
        ],
    ])
));
$allFiles = $filesystem->listContents('Outbound')->toArray();
$response = $filesystem->write('Outbound/info.txt', 'Hello How are you',array());
if($response){
    echo "Success";
}else echo "Error";
print_r($allFiles );
?>

Composer.json 看起来像

{
    "name": "league/flysystem-sftp",
    "description": "Flysystem adapter for SFTP",
    "license": "MIT",
    "authors": [
        {
            "name": "Frank de Jonge",
            "email": "info@frenky.net"
        }
    ],
    "require": {
        "php": ">=5.6.0",
        "league/flysystem-sftp": "^2.1",
        "phpseclib/phpseclib": "~2.0"
    },
    "require-dev": {
        "mockery/mockery": "0.9.*",
        "phpunit/phpunit": "^5.7.25"
    },
    "autoload": {
        "psr-4": {
            "League''Flysystem''Sftp''": "src/"
        }
    }
}