【问题标题】:Secure FTP using private key authentication in java在 java 中使用私钥认证保护 FTP
【发布时间】:2011-12-05 17:13:19
【问题描述】:
import com.jcraft.jsch.*;
import com.jcraft.jsch.JSchException;
import oracle.jdbc.driver.OracleDriver;
import java.io.*;
import java.util.*;
import java.sql.*;
import java.net.*;

public class SecureFTP {

public static void main(String[] args) throws IOException , ClassNotFoundException, JSchException, SftpException{



    JSch jsch = new JSch();
    File file = new File("/home/xxxxx/.ssh/id_rsa");
    Session session = null;
    URL keyFileURL = null;
    URI keyFileURI = null;
    if (file.exists())
    {
        keyFileURL = file.toURL();
        if (keyFileURL == null)
        {
            System.out.println("what");
            throw new RuntimeException("Key file not found in classpath");
        }
    }
    else System.out.println("FIle not found");
    try{
             keyFileURI = keyFileURL.toURI();
    }
    catch(Exception URISyntaxException)
    {
        System.out.println("Wrong URL");
}


    String privateKey = ".ssh/id_rsa";

    //jsch.addIdentity(privateKey);

    jsch.addIdentity(new File(keyFileURI).getAbsolutePath());
    System.out.println(new File(keyFileURI).getAbsolutePath() + " LOL");
    session = jsch.getSession("username", "servername");
    //session.setPassword("password");

    java.util.Properties config = new java.util.Properties();
    config.put("StrictHostKeyChecking", "no");
    session.setConfig(config);

    // connect
    session.connect();

    // get SFTP channel
    Channel channel = session.openChannel("sftp");
    channel.connect();
    ChannelSftp schannel = (ChannelSftp) channel;

    FileInputStream fis = new FileInputStream(sourcefile);
    schannel.put(fis, destinationfile );
    fis.close();



}

    schannel.exit();
    session.disconnect();

}

}

正如您从我注释掉的代码中看到的那样,我已经尽一切可能让它工作,唯一有效的是我直接设置密码。我正在尝试使用生成的 RSA 私钥,但我不断收到身份验证失败。

我已将公钥添加到目标服务器上的授权密钥列表中。而且没有密码。

还有什么我应该做的吗?比如说,在生成密钥时?我缺少一个步骤吗?

我可以使用另一个库来实现相同的功能吗?

【问题讨论】:

  • 您能否在服务器上的 syslog 文件中查看为什么身份验证失败?
  • 如果这是 Linux 服务器,那么 /var/log/messages 可能吗?询问您的系统管理员或本地 IT。

标签: java solaris rsa sftp private-key


【解决方案1】:

确保存在必要的文件(客户端上的 id_rsa 和 id_rsa.pub,服务器上的 authorized_keys)。确保您可以通过使用这些文件的其他工具(例如 ssh)使用公钥身份验证。

如果看起来没问题,问题可能出在您的 Java 安全提供程序上。如果您认为自己的文件正确,请继续阅读。

RSA 私钥存储有不同的格式,而 SSH 使用一种不标准的格式。大多数提供者都希望有一个称为 CRT RSA 密钥的东西,当 JSch 没有给他们提供该格式的密钥时,他们会引发一个异常,JSch 会默默地吃掉并继续下一个身份验证方法。

您的提供商是什么?下面的sn-p帮你一探究竟:

import java.security.KeyFactory;
…

KeyFactory f = KeyFactory.getInstance("RSA");
System.out.println(f.getProvider().getName());

更新:我做了一些检查,从 Java 5 开始,SunPKCS11 提供程序安装在 Solaris 系统上的优先级最高,以提高性能。由于我不运行 Solaris,因此无法对其进行测试,但我相信这可能会导致问题。

JSch 不允许您通过其 API 指定用于此操作的提供程序,因此您必须更改已安装提供程序的优先级。事实上,我建议尝试从这个应用程序中删除 SunPKCS11;在您的应用程序启动时运行此代码一次:

Security.removeProvider("SunPKCS11-Solaris");

【讨论】:

  • 提供者是 SunPKCS11-Solaris。我确保这些密钥存在并且能够使用这些密钥进行 sftp 和 ssh(即没有密码/密码)。但是,对于 jsch,它给了我这个例外。如何确保格式符合要求?
  • @roymustang86 好的,这很奇怪。默认情况下,Oracle JVM 应该使用 SunRsaSign 提供程序来创建 RSA 密钥,它可以处理这种情况。 PKCS11 提供程序是可插拔的,所以它可以是任何东西,但通常你会使用存储在硬件中的密钥,比如智能卡。如果您的系统上有智能卡读卡器或硬件加密模块,那么 PKCS11 提供程序可能已被配置为首选,这确实可能导致问题。像这样列出您的提供商:for (Provider p : Security.getProviders()) System.out.println(p.getName());
  • 列表顺序如下:SunPKCS11-Solaris SUN SunRsaSign SunJSSE SunJCE SunJGSS SunSASL
  • 非常感谢,我永远不会知道如何解决这个问题。
  • 是的,JSch 在错误处理、错误报告和提供程序配置方面的质量并没有给我留下深刻印象。
【解决方案2】:

您是否已将密钥复制到目标服务器上的 $HOME/.ssh/authorized_keys 文件中?如果是这样,您可能应该提到这一点。如果没有,则需要这样做才能正常工作。另外,您是否在没有密码的情况下生成密钥?如果私钥受密码保护,您需要将该密码提供给addIdentity

在验证了这些事情之后,我建议尝试使用 OpenSSH 通过命令行进行连接,因为您在此处的 Java 代码看起来是正确的。如果命令行不起作用,请使用 -vvv 调用它以获取有关它正在做什么的详细输出。可能是服务器配置了PubkeyAuthentication 设置为no。

【讨论】:

  • 用该信息更新了问题,我将公钥复制到了授权密钥。即 /.ssh/id_rsa.pub 到另一台服务器上的 authorized_keys
猜你喜欢
  • 2011-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-24
  • 1970-01-01
  • 2016-03-04
  • 2018-07-30
  • 1970-01-01
相关资源
最近更新 更多