在java中使用私钥身份验证来保护FTP
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 私钥,但始终出现身份验证失败。
我已将公钥添加到目标服务器上的授权密钥列表中。并且没有密码。
还有什么我应该做的吗?就像说,在生成密钥时?我缺少一个步骤吗?
我可以使用另一个库来实现相同的功能吗?
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();
}
}
As you can see from the code I have commented out, I have tried everything possible to get this working and the only thing that works is if I set the password directly. I am trying to use the RSA private key generated, but I keep getting an auth fail.
I have added the public key to the list of authorized keys on the target server. And there is no passphrase.
Is there something else I am supposed to do? Like say, while generating the keys? Is there a step I am missing?
Is there another library I can use to implement the same function?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
确保必要的文件存在(客户端上有 id_rsa 和 id_rsa.pub,服务器上有authorized_keys)。确保您可以使用这些文件通过其他工具(例如
ssh
)使用公钥身份验证。如果看起来没问题,则问题可能出在您的 Java 安全提供程序上。如果您认为您拥有正确的文件,请继续阅读。
RSA 私钥存储有不同的格式,而 SSH 使用一种非标准格式。大多数提供商都期望使用称为 CRT RSA 密钥的东西,当 JSch 没有向他们提供该格式的密钥时,他们会引发异常,JSch 会默默地处理该异常并继续执行下一个身份验证方法。
您的提供商是什么?以下代码片段将帮助您找到答案:
更新:我做了一些检查,从 Java 5 开始,SunPKCS11 提供程序在 Solaris 系统上以最高优先级安装,以提高性能。由于我不运行 Solaris,因此无法测试它,但我相信这可能是导致问题的原因。
JSch 不允许您通过其 API 指定用于此操作的提供程序,因此您必须更改已安装提供程序的优先级。事实上,我建议尝试从该应用程序中删除 SunPKCS11;当您的应用程序启动时运行此代码一次:
Make sure the necessary files exist (id_rsa and id_rsa.pub on the client, authorized_keys on the server). Make sure you can use public key authentication with another tool, like
ssh
, using these files.If that looks alright, the problem may be with your Java security provider. Read on if you think you have the right files in place.
There are different formats for RSA private key storage, and SSH uses one that is not standard. Most providers expect something called a CRT RSA key, and when JSch doesn't give them a key in that format, they raise an exception which JSch silently eats and goes on to the next authentication method.
What is your provider? The following snippet will help you find out:
Update: I did some checking around, and as of Java 5, the SunPKCS11 provider is installed with the highest precedence on Solaris systems, for performance. Since I don't run Solaris, I can't test it, but I believe this may be causing the problem.
JSch doesn't allow you to specify the provider to use for this operation through its API, so you will have to change the precedence of the installed providers. In fact, I'd suggest trying to remove the SunPKCS11 from this application; run this code once when your application starts up:
您是否已将密钥复制到目标服务器上的文件 $HOME/.ssh/authorized_keys 中?如果是这样,你可能应该提到这一点。如果没有,则需要这样做才能发挥作用。另外,您生成的密钥是否没有密码?如果私钥受密码保护,您需要向
addIdentity
提供该密码。验证这些内容后,我建议尝试使用 OpenSSH 通过命令行进行连接,因为此处的 Java 代码看起来是正确的。如果命令行不起作用,请使用 -vvv 调用它以获取有关其正在执行的操作的详细输出。服务器配置的
PubkeyAuthentication
可能设置为 no。Have you have copied the key into the file $HOME/.ssh/authorized_keys on the target server? If so, you should probably mention that. If not, that is required for this to work. Also, are you generating the key without a password? If the private key is password protected, you will need to provide that password to
addIdentity
.After verifying those things, I'd recommend trying to connect via the command line using OpenSSH, as the Java code you have here looks correct. If the command line does not work, invoke it with -vvv to get verbose output about what it is doing. It is possible that the server is configured with
PubkeyAuthentication
set to no.