背景
日常工作中,有時候需要用程式碼去操作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;
}
}
};
}
複製程式碼
後記
總之,工具並不難,本文主要涉及到公鑰私鑰驗證的原理相關,搞懂了原理,進行操作就不難了.