PHP中Curl连接SFTP认证失败(OpenSSH连接正常)
问题分析与解决方案
从你提供的日志和代码来看,核心问题集中在PHP CURL的SSH认证配置、密钥路径处理以及运行环境权限上,以下是针对性的修复步骤:
1. 修复密钥路径的语法错误
你的代码中CURLOPT_SSH_PUBLIC_KEYFILE和CURLOPT_SSH_PRIVATE_KEYFILE的值未加引号,PHP会将mypublickey和myprivatekey当作未定义常量处理,导致CURL无法定位密钥文件。必须用字符串形式传入完整的绝对路径:
// 替换为你的实际密钥绝对路径 curl_setopt($curlHandler, CURLOPT_SSH_PUBLIC_KEYFILE, '/home/your-user/.ssh/id_rsa.pub'); curl_setopt($curlHandler, CURLOPT_SSH_PRIVATE_KEYFILE, '/home/your-user/.ssh/id_rsa');
优先使用绝对路径,避免PHP运行时因工作目录差异找不到文件。
2. 强制禁用SSH Agent,指定仅公钥认证
日志中的Failure connecting to agent说明CURL默认尝试通过SSH Agent获取密钥,但PHP运行环境(如Web服务器进程)通常未加载Agent。添加以下配置强制使用指定密钥文件认证:
// 强制仅使用公钥认证,不依赖SSH Agent curl_setopt($curlHandler, CURLOPT_SSH_AUTH_TYPES, CURLSSH_AUTH_PUBLICKEY);
3. 验证PHP进程的密钥访问权限
即使你已将密钥文件权限设为600,也要确认PHP运行的系统用户(如www-data、apache)能读取密钥文件:
- 将密钥复制到PHP有权访问的目录(如
/var/www/.ssh/) - 设置文件权限:
chmod 600 /var/www/.ssh/id_rsa - 设置目录权限:
chmod 700 /var/www/.ssh/ - 调整所有者:
chown www-data:www-data /var/www/.ssh/ -R
4. 检查密钥格式兼容性
OpenSSH生成的现代密钥格式(如ssh-ed25519)可能存在兼容性问题,若使用此类密钥,可转换为RSA格式(4096位):
ssh-keygen -t rsa -b 4096 -f /path/to/new_rsa_key
将新公钥上传到SFTP服务器后,在PHP代码中改用新密钥路径。
完整修复后的代码示例
$dest = 'sftp://myusername@mydestination:22'; $curlHandler = curl_init(); curl_setopt($curlHandler, CURLOPT_URL, $dest); curl_setopt($curlHandler, CURLOPT_PROTOCOLS, CURLPROTO_SFTP); curl_setopt($curlHandler, CURLOPT_VERBOSE, true); // 修复密钥路径(替换为实际绝对路径) curl_setopt($curlHandler, CURLOPT_SSH_PUBLIC_KEYFILE, '/var/www/.ssh/id_rsa.pub'); curl_setopt($curlHandler, CURLOPT_SSH_PRIVATE_KEYFILE, '/var/www/.ssh/id_rsa'); // 强制公钥认证,禁用SSH Agent curl_setopt($curlHandler, CURLOPT_SSH_AUTH_TYPES, CURLSSH_AUTH_PUBLICKEY); // SFTP无需SSL验证,可保留但无实际作用 curl_setopt($curlHandler, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curlHandler, CURLOPT_SSL_VERIFYHOST, false); $resp = curl_exec($curlHandler); // 调试用:捕获CURL错误信息 if(curl_errno($curlHandler)){ echo 'CURL Error: ' . curl_error($curlHandler); } curl_close($curlHandler);
内容的提问来源于stack exchange,提问作者Sacha Durand
相关产品推荐
相关产品推荐

