参考博客地址:
Java 实现 SCP 携带密码拷贝文件 - 龙凌云端 - 博客园、
背景:项目中需要多台服务器之间进行文件传输,起初,使用的是密码认证的方式,但是服务器的密码会每三个月强制修改一次,这会影响到文件的正常传输,所以后面考虑使用ssh 公钥的认证方式
1、linux 不同服务器scp免密远程传输文件实例 ssh 免密登录 配置
本步骤参考本人博客:linux 不同服务器scp免密远程传输文件实例 ssh 免密登录_chen_lay的博客-CSDN博客
2、java 实现 ssh scp 免密(公钥)多服务器间的文件传输
a、maven依赖
<!-- https://mvnrepository.com/artifact/org.apache.sshd/sshd-common -->
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-common</artifactId>
<version>2.7.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.sshd/sshd-core -->
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-core</artifactId>
<version>2.7.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.sshd/sshd-scp -->
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-scp</artifactId>
<version>2.7.0</version>
</dependency>
b、具体的工具类
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.keyverifier.DefaultKnownHostsServerKeyVerifier;
import org.apache.sshd.client.keyverifier.KnownHostsServerKeyVerifier;
import org.apache.sshd.client.keyverifier.ServerKeyVerifier;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.scp.client.ScpClient;
import org.apache.sshd.scp.client.ScpClientCreator;
import java.io.*;
import java.net.SocketAddress;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
public class ScpClientUtil {
private static String host = "10.186.83.100";
private static String username = "username";
private static String password = "password";
private static Integer port = 22;
private static String local = "/home/mg/data/customer_contract/";
private static String remote = "/home/mg/data/customer_contract/";
private static String idRsaPath = "/home/mg/.ssh/id_ras";
public static void scpFile(String local, String remote, boolean strictHostKey) throws Exception {
long startTime = System.currentTimeMillis();
// 创建 SSH客户端
SshClient client = SshClient.setUpDefaultClient();
KnownHostsServerKeyVerifier verifier = new DefaultKnownHostsServerKeyVerifier(new ServerKeyVerifier() {
@Override
public boolean verifyServerKey(ClientSession clientSession, SocketAddress remoteAddress,
PublicKey serverKey) {
return !strictHostKey;
}
}, true);
client.setServerKeyVerifier(verifier);
// 启动 SSH客户端
client.start();
// 通过主机IP、端口和用户名,连接主机,获取Session
ClientSession session = client.connect(username, host, port).verify().getSession();
// 给Session添加密码
// session.addPasswordIdentity(password);
// publicKey方式认证
session.addPublicKeyIdentity(getKeyPairFromString(readPemFile(new File(idRsaPath))));
// 校验用户名和密码的有效性
boolean isSuccess = session.auth().verify(10000L).isSuccess();
// 认证成功
if (isSuccess) {
long middleTime = System.currentTimeMillis();
System.out.println("Connect host cost time: " + (middleTime - startTime) / 1000.0 + "s.");
ScpClientCreator creator = ScpClientCreator.instance();
// 创建 SCP 客户端
ScpClient scpClient = creator.createScpClient(session);
System.out.println("Scp beginning.");
// ScpClient.Option.Recursive:递归copy,可以将子文件夹和子文件遍历copy
scpClient.upload(local, remote);
scpClient.download(remote, local);
System.out.println("Scp finished.");
// 释放 SCP客户端
if (scpClient != null) {
scpClient = null;
}
// 关闭 Session
if (session != null && session.isOpen()) {
session.close();
}
// 关闭 SSH客户端
if (client != null && client.isOpen()) {
client.stop();
client.close();
}
}
long endTime = System.currentTimeMillis();
System.out.println("Total Cost time: " + (endTime - startTime) / 1000.0 + "s.");
}
/**
* 读取文件内容
*/
public static String readPemFile(File f) throws IOException {
try (InputStream is = Files.newInputStream(f.toPath());
DataInputStream dis = new DataInputStream(is)) {
byte[] bytes = new byte[(int) f.length()];
dis.readFully(bytes);
return new String(bytes);
} catch (InvalidPathException e) {
throw new IOException(e);
}
}
/**
* 获取密钥对
*/
static KeyPair getKeyPairFromString(String pk) throws IOException, NoSuchAlgorithmException {
final KeyPairGenerator rsa = KeyPairGenerator.getInstance("RSA");
final KeyPair keyPair = rsa.generateKeyPair();
final ByteArrayOutputStream stream = new ByteArrayOutputStream();
stream.write(pk.getBytes());
final ObjectOutputStream o = new ObjectOutputStream(stream);
o.writeObject(keyPair);
return keyPair;
}
public static void main(String[] args) throws Exception {
scpFile(local, remote, false);
}
}
c、执行结果:
Connect host cost time: 3.533s. Scp beginning. Scp finished. Total Cost time: 4.545s.