实现
1️⃣ pom
依赖:
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>6.6.0.202305301015-r</version>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.ssh.jsch</artifactId>
<version>6.5.0.202303070854-r</version>
</dependency>
2️⃣ JschConfigSessionFactory
配置:
JSch与JGit
JSch
是一个纯 Java 实现的 SSH2 协议库,它提供了在 Java 程序中进行 SSH 通信的功能。JSch
允许你在 Java 应用程序中使用 SSH 协议进行远程命令执行、文件传输和端口转发等操作。
JGit
是一个用于访问 Git 版本控制系统的 Java 库,它提供了在 Java 应用程序中与 Git 仓库进行交互的功能。JGit
是 Eclipse Foundation 的一个项目,旨在为 Java 开发者提供一个功能齐全且易于集成的 Git 客户端库。
JschConfigSessionFactory
是基于 JSch
的一个辅助类,用于在 JGit
中配置 SSH 会话工厂。
配置
SshSessionFactory sshSessionFactory = new JschConfigSessionFactory() {
@Override
protected void configure(OpenSshConfig.Host host, Session session) {
// 设置 SSH 客户端在连接远程服务器时不进行严格的主机密钥检查
session.setConfig("StrictHostKeyChecking", "no");
}
@Override
protected JSch createDefaultJSch(FS fs) throws JSchException {
JSch jSch = super.createDefaultJSch(fs);
// 添加私钥文件用于身份验证
jSch.addIdentity(privateKey);
return jSch;
}
};
JschConfigSessionFactory
工作流程
在JGit
中,首先createSession()
方法被调用,方法内部调用getJSch()
获取JSch
实例,再调用JSch
实例的getSession()
方法获取Session
对象。
getJSch()
方法被调用时,createDefaultJSch()
方法于内部被调用。
原始的createDefaultJSch()
方法中,configureJSch()
方法会被调用,但原始的configureJSch()
方法内部为空。
createSession()
方法中会调用configure()
方法。
主机密钥检查
主机密钥检查(Host Key Checking)是在 SSH 连接过程中进行的一种安全机制,用于验证远程主机的身份和防止中间人攻击。
在 SSH 连接过程中,当客户端(例如使用 JSch 库的应用程序)首次连接到一个远程主机时,远程主机会返回自己的公钥。为了确保连接的远程主机是预期的主机而不是中间人,客户端会对远程主机的公钥进行验证。
主机密钥检查的过程如下:
-
客户端收到远程主机的公钥。
-
客户端会将远程主机的公钥与本地存储的已知主机密钥进行比较。
- 如果已知主机密钥列表中存在与远程主机公钥匹配的密钥,表示该远程主机的身份是可信的,连接将继续进行。
- 如果已知主机密钥列表中不存在匹配的密钥,表示该远程主机的身份是不可信的或是首次连接的主机,客户端会触发主机密钥检查流程。
- 主机密钥检查的具体行为取决于 SSH 客户端的配置:
- 如果客户端的配置指定了接受新的主机密钥,客户端将自动接受远程主机的公钥,并将其添加到已知主机密钥列表中。这种配置一般用于自动化脚本等场景。
- 如果客户端的配置要求用户手动确认新的主机密钥,客户端会提示用户确认该主机的公钥指纹是否可信。用户需要进行手动确认才能继续连接。
- 如果客户端的配置指定了拒绝新的主机密钥,连接将被终止,并抛出异常或给出相应的错误提示。
3️⃣ 指定一不存在或为空的目录
Path tempDirectory = Paths.get("d:/tmp");
4️⃣ 基于JGit拉代码
try (Git git = Git.cloneRepository()
.setURI(sshUrl)
// 用于在回调中将自定义的session工厂配置到JGit中
.setTransportConfigCallback(transport -> {
SshTransport sshTransport = (SshTransport) transport;
sshTransport.setSshSessionFactory(sshSessionFactory);
})
.setDirectory(new File(String.valueOf(tempDirectory)))
// 禁用自动`checkout`,使得工作目录下不会出现克隆的文件,便于后续拉取指定id的代码
.setNoCheckout(true)
.call()) {
// 解析commit-id
ObjectId commitObjectId = git.getRepository().resolve(commitId);
//
git.checkout().setName(commitObjectId.getName()).call();
}