Статьи

Использование SSH и SFTP с PHP

В современном мире с таким количеством сторонних интеграций и совместного использования контента важно понимать и использовать такие протоколы, как SCP и SFTP. Расширение PHP SSH2, оболочка для libssh2, которая реализует протокол SSH2, предоставляет несколько функций, которые вы можете использовать для безопасной передачи файлов.

Чтобы начать использовать эти функции, очевидно, что необходимо установить пакет SSH2 . Поскольку это расширение PECL, процесс установки будет зависеть от выбранной вами операционной системы. Следуйте инструкциям на php.net .

Установление соединения

Давайте начнем с подключения к сервису SSH. Установить соединение так же просто, как:

<?php $conn = ssh2_connect('example.com', 22); ssh2_auth_password($conn, 'username', 'password'); 

Некоторые администраторы предпочитают использовать открытый и закрытый ключи для аутентификации при входе в систему. Если служба настроена и вы хотите подключиться таким образом, вы должны использовать следующее:

 <?php $conn = ssh2_connect('example.com', 22); ssh2_auth_pubkey_file( $conn, 'username', '/home/username/.ssh/id_rsa.pub', '/home/username/.ssh/id_rsa' ); 

Используете ли вы имя пользователя / пароль или аутентификацию с открытым / закрытым ключом, ssh2_auth_password() и ssh2_auth_pubkey_file() оба возвращают логическое значение, указывающее, была ли аутентификация успешной.

Выполнение основных команд

После успешной аутентификации на сервере вы можете выполнять операции передачи файлов. Функции SCP позволяют отправлять или получать файл (ы), например:

 <?php // send a file ssh2_scp_send($conn, '/local/filename', '/remote/filename', 0644); // fetch file ssh2_scp_recv($conn, '/remote/filename', '/local/filename'); 

ssh2_scp_send() есть дополнительный параметр, который позволяет указать, каким должно быть разрешение файла на удаленном сервере при копировании файла.

Больше функциональности доступно с функциями SFTP; Вы можете изменить права доступа к файлу или каталогу, получить информацию о файле, создать каталоги, переименовать элементы, удалить элементы и т. д. Они работают ssh2_sftp() же, как и функции SCP, описанные выше, но перед использованием функции:

 <?php $sftp = ssh2_sftp($conn); // Create a new folder ssh2_sftp_mkdir($sftp, '/home/username/newdir'); // Rename the folder ssh2_sftp_rename($sftp, '/home/username/newdir', '/home/username/newnamedir'); // Remove the new folder ssh2_sftp_rmdir($sftp, '/home/username/newnamedir'); // Create a symbolic link ssh2_sftp_symlink($sftp, '/home/username/myfile', '/var/www/myfile'); // Remove a file ssh2_sftp_unlink($sftp, '/home/username/myfile'); 

ssh2_sftp() принимает ресурс соединения и возвращает ресурс SFTP, который будет использоваться в будущих ssh2_sftp_ *. Затем вызовы возвращают логическое значение, которое позволяет определить, было ли действие успешным.

Использование функций Wrapper

Когда для SFTP или SCP не существует определенной функции управления файлами, обычно функция основной файловой системы будет работать с использованием потоковой оболочки. Ниже приведены несколько примеров:

 <?php // Create a new folder mkdir('ssh2.sftp://' . $sftp . '/home/username/newdir'); // Remove the new folder rmdir('ssh2.sftp://' . $sftp . '/home/username/newdir'); // Retrieve a list of files $files = scandir('ssh2.sftp://' . $sftp . '/home/username'); 

Перед выполнением любого из этих вызовов необходимо установить соединение с сервером SSH и SFTP, так как он использует ранее созданную переменную $sftp .

Собери все вместе

Теперь, когда вы можете подключать, аутентифицировать и выполнять команды на SSH-сервере, мы можем создать несколько вспомогательных классов для упрощения процесса выполнения этих команд: один для выполнения вызовов SCP и один для вызовов SFTP, родительский класс для общих функциональность и пара классов для инкапсуляции информации аутентификации (пароль и ключи).

Давайте сначала создадим классы аутентификации, так как они будут использоваться другими классами.

 <?php class SSH2Authentication { } 
 <?php class SSH2Password extends SSH2Authentication { protected $username; protected $password; public function __construct($username, $password) { $this->username = $username; $this->password = $password; } public function getUsername() { return $this->username; } public function getPassword() { return $this->password; } } 
 <? class SSH2Key extends SSH2Authentication { protected $username; protected $publicKey; protected $privateKey; public function __construct($username, $publicKey, $privateKey) { $this->username = $username; $this->password = $password; } public function getUsername() { return $this->username; } public function getPublicKey() { return $this->publicKey; } public function getPrivateKey() { return $this->privateKey; } } 

SSH2Password и SSH2Key просто оборачивают свою соответствующую информацию аутентификации. Они имеют общий базовый класс, поэтому мы можем воспользоваться подсказками типов PHP при передаче экземпляров их потребителям.

Двигаясь дальше, давайте создадим SSH2 для подключения и аутентификации на сервере SSH.

 <?php class SSH2 { protected $conn; public function __construct($host, SSH2Authentication $auth, $port = 22) { $this->conn = ssh2_connect($host, $port); switch(get_class($auth)) { case 'SSH2Password': $username = $auth->getUsername(); $password = $auth->getPassword(); if (ssh2_auth_password($this->conn, $username, $password) === false) { throw new Exception('SSH2 login is invalid'); } break; case 'SSH2Key': $username = $auth->getUsername(); $publicKey = $auth->getPublicKey(); $privateKey = $auth->getPrivateKey(); if (ssh2_auth_pubkey_file($this->conn, $username, $publicKey, $privateKey) === false) { throw new Exception('SSH2 login is invalid'); } break; default: throw new Exception('Unknown SSH2 login type'); } } } 

Будет создан очень простой класс SCP, расширяющий SSH2 и использующий магический метод __call() . Это позволяет нам делать две важные вещи: автоматически добавлять «ssh_scp_» к вызову функции и предоставлять переменную соединения для вызова.

 <?php class SSH2SCP extends SSH2 { public function __call($func, $args) { $func = 'ssh2_scp_' . $func; if (function_exists($func)) { array_unshift($args, $this->conn); return call_user_func_array($func, $args); } else { throw new Exception( $func . ' is not a valid SCP function'); } } } 

Класс SFTP очень похож, хотя его конструктор перегружен и выполняет ssh2_sftp() . Результаты сохраняются в защищенной переменной и автоматически добавляются ко всем вызовам функций SFTP.

 <?php class SSH2SFTP extends SSH2 { protected $sftp; public function __construct($host, ISSH2Authentication $auth, $port = 22) { parent::__construct($host, $auth, $port); $this->sftp = ssh2_ftp($this->conn); } public function __call($func, $args) { $func = 'ssh2_sftp_' . $func; if (function_exists($func)) { array_unshift($args, $this->sftp); return call_user_func_array($func, $args); } else { throw new Exception( $func . ' is not a valid SFTP function'); } } } 

После создания этих классов их можно использовать для выполнения вызовов функций SCP и SFTP. Благодаря полезным методам __call в обоих классах нам не нужно передавать открытое соединение или повторно вводить «ssh2_scp_» или «ssh2_ftp_» при каждом вызове.

 <?php // Create SCP connection using a username and password $scp = new SCP( 'example.com', new SSH2Password('username', 'password') ); // Receive a file via SCP if ($scp->recv('remote/file', 'local/file')) { echo 'Successfully received file'; } // Create SFTP connection using a public/private key $sftp = new SSH2SFTP( 'example.com', new SSH2Key('username', 'public_key', 'private_key') ); // Create a directory via SFTP if ($sftp->mkdir('directory/name')) { echo 'Successfully created directory'; } 

Резюме

Устанавливая расширение SSH2 PHP, оно предоставляет вашим сценариям возможность подключения к серверам SSH2. Вы можете использовать удобные классы, которые упрощают код для выполнения вызовов SFTP или SCP, или, если конкретная функция не предоставляется библиотекой, большинство операций основной файловой системы можно использовать, используя функциональность оболочки SSH2.

Изображение через Fotolia