背景
日常工作中,有时候需要用代码去操作gitlab
或者github
实现自动化部署,持续集成,持续部署等功能,本文就 Java 操作 git 相关的权限验证进行实践总结.
工具
使用的工具为eclipse
的jgit
,pom为目前最新版本.
<!-- https://mvnrepository.com/artifact/org.eclipse.jgit/org.eclipse.jgit -->
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>5.2.1.201812262042-r</version>
</dependency>
复制代码
权限验证
当然要进行操作 gitlab,无论是检测仓库是否存在,或者 clone 代码,切换分支等操作,都需要首先验证权限,本文主要讲解两种验证方式,用户名密码
和 公钥私钥
验证.一下使用git ls-remote
来验证
用户名密码验证
用户名密码验证只能用于http
类型的仓库,实例如下:
CredentialsProvider credentialsProvider = new UsernamePasswordCredentialsProvider("username","password");
Map<String, Ref> asMap = Git.lsRemoteRepository()
.setRemote("http://gitlab.xxx.com/arch/aabb.git")
.setCredentialsProvider(credentialsProvider)
.callAsMap();
复制代码
如果用户名密码没问题,验证就可以通过了.
SSH验证
上面展示的是http
类型的仓库,如果地址是 git
类型的,就要使用公钥私钥
进行验证.比如git@gitlab.xxxx.com:arch/aabb.git
利用主机上的私钥和known_hosts
进行验证
这也是默认的形式. ssh 验证需要先创建一个JschConfigSessionFactory
,然后在这个对象中进行权限的配置,如果不配置,就默认使用系统的私钥和 known_hosts
.这段逻辑在JschConfigSessionFactory
的createDefaultJSch
方法中,感兴趣的同学可以自行查看源码.
SshSessionFactory sshSessionFactory = new JschConfigSessionFactory() {
@Override
protected void configure(OpenSshConfig.Host host, Session session) {
}
};
LsRemoteCommand command = Git.lsRemoteRepository();
command.setRemote("git@gitlab.xxxx.com:data/aabb.git");
command.setHeads(false);
// command 和 sshSessionFactory 关联,进行验证.
TransportConfigCallback callback = transport -> {
SshTransport sshTransport = (SshTransport) transport;
sshTransport.setSshSessionFactory(sshSessionFactory);
};
command.setTransportConfigCallback(callback);
Map<String, Ref> stringRefMap = command.callAsMap();
...
复制代码
使用自定义的私钥和known_hosts
进行验证.
如果你的代码需要部署带不同的机器上,而又不想依赖主机的配置,那么可以通过自定义配以读取特定的文件,进行配置,使用如下,修改SshSessionFactory
相关配置:
SshSessionFactory sshSessionFactory = new JschConfigSessionFactory() {
@Override
protected void configure(OpenSshConfig.Host host, Session session) {
//如果有密码;
//session.setPassword("123");
}
@Override
protected JSch createDefaultJSch(FS fs) throws JSchException {
JSch defaultJSch = new JSch();
//私钥文件的路径,可放在项目目录中
defaultJSch.addIdentity(file);
//git 仓库域名对应的known_hosts文件,可放在项目目录中
defaultJSch.setKnownHosts(known_hosts);
return defaultJSch;
}
};
复制代码
使用上面的例子进行验证,如果配置正确,就可以通过ssh
的校验了.
最佳实践
实际编写过程中,会重复使用SshSessionFactory
,并且addIdentity
和setKnownHosts
都要使用内存中的inputstream
操作,避免框架在反查文件 file 的时候找不到文件(SpringBoot),代码如下:
@PostConstruct
private void init() throws IOException {
sshSessionFactory = new JschConfigSessionFactory() {
@Override
protected void configure(OpenSshConfig.Host host, Session session) {
}
@SneakyThrows
@Override
protected JSch createDefaultJSch(FS fs) throws JSchException {
try (InputStream fileInputStream = Utils.loadAsInputStream("git/private.key");
InputStream knownHostInputStream = Utils.loadAsInputStream("git/known_hosts")) {
JSch defaultJSch = new JSch();
defaultJSch.addIdentity(Utils.getRandomString(), IOUtils.toByteArray(fileInputStream), null, null);
defaultJSch.setKnownHosts(knownHostInputStream);
return defaultJSch;
}
}
};
}
复制代码
后记
总之,工具并不难,本文主要涉及到公钥私钥验证的原理相关,搞懂了原理,进行操作就不难了.