PHP Conference Japan 2024

ssh2_auth_pubkey_file

(PECL ssh2 >= 0.9.0)

ssh2_auth_pubkey_file使用公钥进行身份验证

描述

ssh2_auth_pubkey_file(
    资源 $session,
    字符串 $username,
    字符串 $pubkeyfile,
    字符串 $privkeyfile,
    字符串 $passphrase = ?
): 布尔值

使用从文件中读取的公钥进行身份验证。

参数

session

一个 SSH 连接链接标识符,从对 ssh2_connect() 的调用中获得。

username

pubkeyfile

公钥文件需要使用 OpenSSH 的格式。它应该类似于

ssh-rsa AAAAB3NzaC1yc2EAAA....NX6sqSnHA8= rsa-key-20121110

privkeyfile

passphrase

如果 privkeyfile 已加密(应该加密),则必须提供 passphrase

返回值

成功时返回 true,失败时返回 false

示例

示例 #1 使用公钥进行身份验证

<?php
$connection
= ssh2_connect('shell.example.com', 22, array('hostkey'=>'ssh-rsa'));

if (
ssh2_auth_pubkey_file($connection, 'username',
'/home/username/.ssh/id_rsa.pub',
'/home/username/.ssh/id_rsa', 'secret')) {
echo
"公钥身份验证成功\n";
} else {
die(
'公钥身份验证失败');
}
?>

注释

注意:

底层的 libssh 库不支持非常干净的部分身份验证。也就是说,如果您需要同时提供公钥和密码,则此函数似乎已失败。在这种特定情况下,此调用的失败可能仅意味着身份验证尚未完成。您需要忽略此失败并继续,并调用 ssh2_auth_password() 以完成身份验证。

添加注释

用户贡献的注释 11 条注释

Aurelien Marchand
2 年前
我们合作的供应商要求同时使用密码身份验证和公钥/私钥身份验证。

经过多次痛苦的测试,我们找到了解决方法,绕过了安装 phpseclib 的需要

<?php

$server
= "subdomain.example.com";
$username = "username";
$password = "password";
$path_to_public_key = "file.pub";
$path_to_private_key = "file.priv"; // 关键:权限必须为 0600!
$path_to_needed_file = "/path/to/file/needed.txt";

$ssh2 = ssh2_connect($server);
@
ssh2_auth_pubkey_file($ssh2,$username,$path_to_public_key,$path_to_private_key); // 此处会返回警告,但这是正常的,可以忽略
ssh2_auth_password($ssh2,$username,$password);
$sftp = ssh2_sftp($ssh2);
$file = fopen("ssh2.sftp://" . intval($sftp). $path_to_needed_file,"r");
$content = fread($file,1024);
fclose($file);
ssh2_disconnect($ssh2);

echo
$content;
?>
miloslav dot hula at gmail dot com
4 年前
如果您在使用 RSA 密钥时遇到问题,请检查私钥文件内容是否以

-----BEGIN RSA PRIVATE KEY-----

开头,而不是

-----BEGIN OPENSSH PRIVATE KEY-----

第一个可以通过以下方式创建:

ssh-keygen -m PEM -t rsa -f mykey
mrpetovan at gmail dot com
8 年前
注意密钥文件路径中的波浪号 (~),因为它们会触发以下警告(在调试版本中)

PHP Warning: String is not zero-terminated (ZZZZZZZZZZZZZZZZZZ1wjj*=?<) (source: Zend/zend_execute.h:81) in Unknown on line 0

尽管身份验证会成功。

<?php
$ssh_conn
= ssh2_connect('test.host.com', 22, array('hostkey' => 'ssh-rsa'));
ssh2_auth_pubkey_file($ssh_conn, 'user', '~/.ssh/id_rsa.pub', '~/.ssh/id_rsa')
?>

以上代码将抛出警告。

<?php
$ssh_conn
= ssh2_connect('test.host.com', 22, array('hostkey' => 'ssh-rsa'));
ssh2_auth_pubkey_file($ssh_conn, 'user', '/home/user/.ssh/id_rsa.pub', '/home/user/.ssh/id_rsa')
?>

以上代码不会。

如果您想对波浪号进行动态替换,可以使用 posix_getpwuid (https://php.net/manual/en/function.posix-getpwuid.php)
nerak-spelled-backwards at modo dot coop
11 年前
此函数在某些 Linux 安装中存在已知错误 (https://bugs.php.net/bug.php?id=58573):如果您使用 libgcrypt 编译了 libssh2,则无法加密您的私钥。根据错误页面,解决方案是使用 OpenSSL 重新构建 libssh2。(或者不要加密您的私钥,但这似乎是不负责任的。)

这不是错误报告——错误显然正在修复——而是一个供其他人参考的注释,因为我花了至少一个小时的谷歌搜索才意识到问题不在我的代码上。
Christophe
4 年前
用户应该注意错误 78661 https://bugs.php.net/bug.php?id=78661

截至 2020 年 12 月,在某些 Linux 发行版(至少包括 Debian 10 和 Ubuntu 20.04)上,尽管 ssh 守护进程会接受连接,但函数 ssh2_auth_pubkey_file 仍然固执地报告错误。

我花了几个小时才意识到我的代码是正确的,但函数有bug。如果您遇到此bug,可以尝试使用https://php.net/ssh2_auth_password代替...如果适用。
christian at cvj dot se
12年前
在我的运行PHP的Linux Debian服务器与另一台Linux Debian服务器通信时,我在使用RSA密钥进行连接时遇到了一些问题。DSA密钥则可以正常工作。我通过在终端中执行以下操作解决了这个问题:

* ssh-keygen -t rsa
.... PUBFILE
* ssh-keygen -f PUBFILE -e
输出

id_rsa.pub =
ssh-rsa OUTPUT [COMMENT]
max
13年前
好的,您需要使用以下命令格式化公钥:

# ssh-keygen -f id_rsa.pub -i
输出:"ssh-rsa <YOURKEYDATA>"

这对我来说很好用。
deepakssn@gmailcom
14年前
设置公钥认证

1. 使用Putty登录到您要连接的Unix服务器。
2. mkdir .ssh (ssh前有一个点)
3. cd .ssh
4. ssh-keygen -t rsa mykey
5. 输入密码为test
6. ls -al -> 您将找到两个文件mykey和mykey.pub
7. cat mykey.pub >>authorized_keys
8. cat mykey
9. 将屏幕上显示的内容复制到记事本中并保存为"c:\mykey"(带引号)
10. cat mykey.pub
11. 将屏幕上显示的内容复制到记事本中并保存为"c:\mykey.pub"(带引号)

<?php

function my_ssh_disconnect($reason, $message, $language)
{
printf("服务器断开连接,原因代码为[%d],消息为:%s\n", $reason, $message);
}

//打开连接,强制在发送数据包时使用3des-cbc,在接收数据包时使用任何强度的aes加密,在两个方向上都不进行压缩,并使用Group1密钥交换。
$methods = array(
'kex' => 'diffie-hellman-group1-sha1',
'client_to_server' => array(
'crypt' => 'aes256-cbc',
'comp' => 'none',
'mac' => 'hmac-sha1'),
'server_to_client' => array(
'crypt' => 'aes256-cbc',
'comp' => 'none',
'mac' => 'hmac-sha1'));

$callbacks = array('disconnect' => 'my_ssh_disconnect');

// 在Unix服务器上运行命令的函数

function run_cmd($ssh_host, $user_name, $keyfilename, $ssh_command)
{
$connection = ssh2_connect($ssh_host, 22, $methods, $callbacks);
if (!
$connection) die('连接失败');
if (
ssh2_auth_pubkey_file($connection, $user_name, $keyfilename.".pub", $keyfilename, 'test'))
{
echo
"公钥认证成功,用户: $user_name";
}
else
{
die(
'公钥认证失败');
}

$stream = ssh2_exec($connection, $ssh_command);
$i=0;
stream_set_blocking($stream, true);
$line = stream_get_line($stream, 1024, "\n");
while (!
feof($stream))
{
echo
$line.' ';
$line = stream_get_line($stream, 1024, "\n");
$i++;
}
echo
"计数: ".$i;
flush();
unset(
$stream);
}

function
my_ssh_disconnect($reason, $message, $language)
{
printf("服务器断开连接,原因代码为[%d],消息为:%s\n",
$reason, $message);
}

// 主代码

$user_name = "USERID";
$keydir = "c:\\";
$search_string = 'needle';
$keyfilename= $keydir.'mykey';
$ssh_host = "foo.bar.com";
$ssh_command = 'grep "'.$search_string.'" /haystack/*.log';
run_cmd($ssh_host, $user_name, $keyfilename, $ssh_command);

$ssh_command = 'ls -al';
run_cmd($ssh_host, $user_name, $keyfilename, $ssh_command);
?>
anjo2
13年前
RSA密钥可能无法工作,使用DSA密钥兼容性更好。

Linux
ssh-keygen -t dsa
cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh/
chmod -R 600 ~/.ssh/*

PHP
<?php
$methods
= array(
'kex' => 'diffie-hellman-group1-sha1',
'hostkey' => 'ssh-dss',
'client_to_server' => array(
'crypt' => '3des-cbc',
'mac' => 'hmac-md5',
'comp' => 'none'),
'server_to_client' => array(
'crypt' => '3des-cbc',
'mac' => 'hmac-md5',
'comp' => 'none'));
$connect = ssh2_connect('127.0.0.1', 22, $methods);
if(
ssh2_auth_pubkey_file($connect, 'username', '~/.ssh/id_dsa.pub', '~/.ssh/id_dsa'))
{
echo
"公钥认证成功\n";
}
else
{
echo
"公钥认证失败\n";
}
?>
gramo dot gnu at gmail dot com
15年前
我遇到了这个函数的一个恼人的问题,每次我尝试运行它时,它都会返回一个

无法使用公钥认证<用户>

但是,当我尝试直接使用以下命令连接到服务器时
ssh <用户>@<域名>
一切正常...

经过多次尝试,我意识到本地文件受到Apache用户读取保护(它们存储在/home/<用户>/.ssh目录中)。

所以,如果您也遇到此问题,只需在Apache可以读取的位置创建一个新目录,并将密钥放在那里。

我的整个操作步骤如下(Linux和Apache作为服务器和客户端):

首先,我创建一个Apache可以读取的目录

mkdir ~/.newssh_keys
chmod 777 ~/.newssh_keys

(这是一个安全问题,所以您可能需要了解如何使其更安全。)

然后,我在本地服务器上创建密钥,选择~/.newssh_keys/id_dsa作为保存密钥的文件

ssh-keygen -t dsa
...
输入保存密钥的文件(/home/<用户>/.ssh/id_dsa):~/.newssh_keys/id_dsa
...

然后,我必须更改私钥的权限
(这是一个安全问题,所以您可能需要了解如何使其更安全。)

chmod 644 ~/.newssh_keys/id_dsa

我将公钥复制到服务器的.ssh目录
客户端$ scp id_dsa.pub <远程用户>@<服务器域名>:~/.ssh/

然后,我使用传统的ssh连接到服务器,以便将公钥追加到authorized_keys2文件的末尾

服务器$ cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys2

并删除公钥以保持整洁
服务器$ rm ~/.ssh/id_dsa.pub

最后,我在我的PHP脚本中使用此代码



<?php
// 为了确保 Apache 可以读取公钥
// (调试完成后删除此代码)
$pub_key = file_get_contents('~/.newssh_keys/id_dsa.pub');
print
"<pre>";
var_export($pub_key);
print
"</pre>";

// 为了检查私钥
// (调试完成后删除此代码)
$prv_key = file_get_contents('~/.newssh_keys/id_dsa');
print
"<pre>";
var_export($prv_key);
print
"</pre>";

// 最后是连接代码
$connection = ssh2_connect('<server_domain>', 22, array('hostkey', 'ssh-dss'));
if (
ssh2_auth_pubkey_file($connection, '<server_user>',
'~/.newssh_keys/id_dsa.pub',
'~/.newssh_keys/id_dsa')) {
echo
"公钥认证成功\n";
} else {
echo
"公钥认证失败";
}
?>
tekiedude at gmail dot com
17 年前
这可能非常不安全,但如果您在封闭的环境中,您可以自行承担风险运行它。

我试图从服务器 A 获取到服务器 B 的 SSH 访问权限,但服务器 A 以“apache”用户运行 Apache,
我需要服务器 B 上属于 root 用户的文件。所以我需要某种方法让 apache 用户
以 root 用户身份连接到服务器 B。以下是我所做的(两台服务器都运行 Linux - 特别是 CentOS4)

1. ssh-keygen -t rsa -f id_rsa 生成密钥,不设置密码
2. 将 id_rsa.pub 文件追加到服务器 B 的 /root/.ssh/authorized_keys2
3. 将 id_rsa 和 id_rsa.pub 文件复制到 /var/www/.ssh/ 等目录
(恰好是 CentOS 上 Apache 的主目录)
4. chown -R apache.apache /var/www/.ssh

然后您可以像这样连接
$connection = ssh2_connect($server,22,array('hostkey'=>'ssh-rsa'));
if (ssh2_auth_pubkey_file($connection,'root',
'/var/www/.ssh/id_rsa.pub',
'/var/www/.ssh/id_rsa')) {
echo "成功!";
}
else
{
echo "失败 :-(";
}
To Top