实现

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 库的应用程序)首次连接到一个远程主机时,远程主机会返回自己的公钥。为了确保连接的远程主机是预期的主机而不是中间人,客户端会对远程主机的公钥进行验证。

主机密钥检查的过程如下:

  1. 客户端收到远程主机的公钥。

  2. 客户端会将远程主机的公钥与本地存储的已知主机密钥进行比较。

  • 如果已知主机密钥列表中存在与远程主机公钥匹配的密钥,表示该远程主机的身份是可信的,连接将继续进行。
  • 如果已知主机密钥列表中不存在匹配的密钥,表示该远程主机的身份是不可信的或是首次连接的主机,客户端会触发主机密钥检查流程。
  1. 主机密钥检查的具体行为取决于 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();
}

完整代码


public interface CloneGithubRepository {
public static String privateKey = "C:\\Users\\UserName\\.ssh\\id_ecdsa";
public static String sshUrl = "git@github.com:username/repository_name.git";
public static String commitId = "68d18ccbf5605f16a15f8fb66c21a8b6776c6d8c";
public static void main(String[] args) throws GitAPIException, IOException {
// Set SSH credentials and authentication method
SshSessionFactory sshSessionFactory = new JschConfigSessionFactory() {
@Override
protected void configure(OpenSshConfig.Host host, Session session) {
session.setConfig("StrictHostKeyChecking", "ask");
} @Override
protected JSch createDefaultJSch(FS fs) throws JSchException {
JSch jSch = super.createDefaultJSch(fs);
jSch.addIdentity(privateKey);
return jSch;
}
};
Path tempDirectory = Paths.get("d:/tmp");
// Clone or fetch a repository
try (Git git = Git.cloneRepository()
.setURI(sshUrl)
.setTransportConfigCallback(transport -> {
SshTransport sshTransport = (SshTransport) transport;
sshTransport.setSshSessionFactory(sshSessionFactory);
})
.setDirectory(new File(String.valueOf(tempDirectory)))
.setNoCheckout(true)
.call()) {
ObjectId commitObjectId = git.getRepository().resolve(commitId);
git.checkout().setName(commitObjectId.getName()).call();
}
System.out.println(tempDirectory);
}
}

Bug清单

(1) Caused by: com.jcraft.jsch.JSchException: invalid privatekey: [B@6591f517

原因:ssh免密格式OPENSSH不支持

重新生成:ssh-keygen -t rsa -m PEM

  • ssh-keygen -t rsa

    • 这个命令生成的 RSA 密钥对使用的是默认的密钥格式(OpenSSH 格式)。
  • ssh-keygen -t rsa -m PEM
    • 这个命令生成的 RSA 密钥对使用的是 PEM 格式(Privacy-Enhanced Mail)。不同之处在于,生成的密钥使用了 PEM 编码。

      PEM 格式是一种基于 Base64 编码的文本格式,常用于表示密钥、证书和其他加密相关数据。PEM 格式的密钥可以在许多软件和系统中使用,包括一些 Web 服务器、证书颁发机构等。

(2)

Caused by: org.eclipse.jgit.errors.NoRemoteRepositoryException: git@github.com:username/repository-name.git:
ERROR: You're using an RSA key with SHA-1, which is no longer allowed.
Please use a newer client or a different key type.

原因:2022年3月15日起,github不再支持SHA-1的加密方式。

重新生成:ssh-keygen -t ecdsa -m PEM

ssh-keygen指令选项概述

-t keytype:指定要生成的密钥类型,如 rsa、dsa、ecdsa 或 ed25519。

  • 示例:ssh-keygen -t rsa

-b bits:指定生成密钥时使用的位数。

  • 示例:ssh-keygen -b 4096

-C comment:为生成的密钥添加注释。

  • 示例:ssh-keygen -C "My Key"

-f filename:指定生成的密钥文件的名称和路径。

  • 示例:ssh-keygen -f /path/to/mykey

-N passphrase:设置生成的密钥的密码短语(passphrase),用于加密私钥。

  • 示例:ssh-keygen -N "mypassword"
  • 在 SSH 中,passphrase(密码短语)是为了增加私钥的安全性而设置的一种额外保护层。当你生成或使用一个使用密码短语保护的私钥时,每次使用该私钥时都需要提供密码短语才能解锁私钥。

-p:更改私钥的密码短语(passphrase)。

  • 示例:ssh-keygen -p -f /path/to/mykey

-q:静默模式,减少命令输出。

  • 示例:ssh-keygen -q

-i:导入其他格式的密钥文件并转换为 SSH 格式。

  • 示例:ssh-keygen -i -f /path/to/otherkey

-e:将密钥文件转换为其他格式。

  • 示例:ssh-keygen -e -f /path/to/mykey

-R hostname:从 known_hosts 文件中删除指定主机的记录。

  • 示例:ssh-keygen -R example.com

-m :用于指定生成的密钥文件的格式或导入/导出密钥时的编码格式

  • -m PEM:指定生成的密钥文件使用 PEM 格式编码。这是一种常见的编码格式,适用于多种应用场景。
  • -m PKCS8:指定生成的私钥文件使用 PKCS#8 格式编码。这种格式常用于导入和导出私钥,特别是与其他工具和系统的集成。
  • -m RFC4716:指定生成的密钥文件使用 RFC 4716 格式编码。该格式与 OpenSSH 兼容,可以用于与其他 SSH 实现进行交互。
  • -m SSH2:指定生成的密钥文件使用 SSH2 格式编码。这是 OpenSSH 的早期格式,不常用于现代应用,仅用于特定的兼容性需求。
  • -m FINGERPRINT:显示密钥的指纹信息。

【git】基于JGit通过ssh-url拉取指定commit-id的代码的更多相关文章

  1. git从远程仓库gitLab上拉取指定分支到本地仓库

    例如:将gitLab 上的dev分支拉取到本地 1>与远程仓库建立连接:git remote add origin XXXXX.git 2>使用git branch 查看本地是否具有dev ...

  2. git pull 冲突拉取不到新的代码

    本地文件已经有冲突或者在pull的过程中拉取的文件和本地文件冲突时,拉取不到新的代码,git pull出现报错,如下: 这个时候,如果你有两种选择,如果你需要这些改动,那个你就需要手动解决冲突,然后a ...

  3. 使用VSTS的Git进行版本控制(六)——拉取请求

    使用VSTS的Git进行版本控制(六)--拉取请求 在将代码合并到主干之前,拉取请求让团队对特性分支的更改提供反馈.审阅人可以通过建议修改留下评论,并投票批准或拒绝代码. 任务1:在Visual St ...

  4. git如何拉取指定分支的代码

    问题背景: 新项目还在开发阶段,没有正式对外发布,所以开发同事合并代码到develop上(或者其他名称分支上),而不是到master分支上 通过git拉取代码的时候,默认拉取的是master分支,如下 ...

  5. (转)GitHub Desktop 拉取 GitHub上 Tag 版本代码

    转自:GitHub Desktop 拉取 GitHub上 Tag 版本代码 一直在使用 GitHub Desktop 图形化 git 管理工具,统一项目框架版本时需要切换到ThinkPHP Tag 分 ...

  6. 2017.6.30 使用git新建项目、仓库并拉取、提交代码

    1.在码云上新建一个项目rms 2.在本地指定位置新建仓库,生成.git文件夹 3.同步远程仓库,并拉取最新代码 远程仓库默认名为orgin.可以修改,这里就是用默认名了. 注意:这里使用ssh方式的 ...

  7. git中如何切换分支,拉取分支,合并分支

    idea中如何使用git来做分支的切换合并: https://blog.csdn.net/autfish/article/details/52513465 本地分支与远程分支: https://seg ...

  8. git clone新项目后如何拉取分支代码到本地

    1.git clone git@git.n.xxx.com:xxx/xxx.git 2.git fetch origin dev    命令来把远程dev分支拉到本地 3.checkout -b de ...

  9. git clone新项目后如何拉取其他分支代码到本地

    1.git clone git@git.n.xxx.com:xxx/xxx.git 2.git fetch origin dev 命令来把远程dev分支拉到本地 - - 解读:git fetch命令用 ...

  10. git 拉取指定的远程分支(三种方式)

    直接拉取 git clone -b ants git@github.com:Ants-double/CareerJava.git git clone -b 远程分支名 仓库地址 本地已经有相关的仓库代 ...

随机推荐

  1. Docker介绍下载安装、制作镜像及容器、做目录映射、做端口映射

    在计算机中,虚拟化(英语:Virtualization)是一种资源管理技术,是将计算机的各种实体资源,如服务器.网络.内存及存储等,予以抽象.转换后呈现出来,打破实体结构间的不可切割的障碍,使用户可以 ...

  2. opencv基础

    Python 和 OpenCV 的结合是计算机视觉领域中应用最为广泛的一种方式,它们的结合使得开发者可以快速.高效地完成各种视觉任务.本文将介绍 Python 和 OpenCV 的基础使用,包括安装. ...

  3. Java学习笔记09

    1. 多态 1.1 多态 ​ 多态是指同一种行为具有多种不同的表现形式. 前提 有继承或者实现关系 有方法重写(没有重写多态就没有意义) 父类引用指向子类对象 格式 父类类型 变量名 = new 子类 ...

  4. T-SQL基础教程Day3

    第三章 联接3.1交叉联接交叉联接是最简单的联接类型.交叉联接仅执行一个逻辑查询处理阶段--笛卡尔乘积将一个输入表的每一行与另一个表的所有行匹配SQL Server支持交叉联接的两种标准语法:ANSI ...

  5. java递归算法之老鼠找路

    (上图出自B站韩顺平教育) 从上图的(1,1)处,寻找到(6,5)处的路线,红色格子是障碍 public class MiGong { public static void main(String[] ...

  6. 项目中统计SQL执行缓慢的方案-数据预处理

    使用场景: 由于表数据量巨大,导致一些统计相关的sql执行非常慢,使用户有非常不好的体验,并且sql和数据库已经没有优化空间了.(并且该统计信息数据实时性要求不高的前提下) 解决方案: 整体思路:创建 ...

  7. Godot报错 Node not found: "SubViewport"[一问随笔]

    问题: 使用TextureRect显示SubViewport的内容,结果发生了如下报错 E 0:00:01:0007 get_node: Node not found: "SubViewpo ...

  8. 深度学习03-(图像梯度处理、图像轮廓、图像预处理在AI中的应用)

    深度学习03-计算机视觉基本理论2 深度学习03-(计算机视觉基本理论2) 图像梯度处理 什么是图像梯度 模板运算 均值滤波 高斯滤波 中值滤波 边沿检测 锐化 图像轮廓 什么是图像轮廓 查找和绘制轮 ...

  9. [Pytorch框架] 4.1 Fine tuning 模型微调

    文章目录 4.1 Fine tuning 模型微调 4.1.1 什么是微调 为什么要微调 迁移学习 Transfer Learning 二者关系 4.1.2 如何微调 4.1.3 注意事项 4.1.3 ...

  10. java线程池和多线程的使用详解

    Java 多线程和线程池使用 java多线程实现的几种方法 1.继承Thread类 继承Thread类,重写run方法,创建线程类对象调用start方法启动线程. public class Threa ...