使用 Java 操作 Git-驗證相關

candyleer發表於2019-02-23

背景

日常工作中,有時候需要用程式碼去操作gitlab 或者github實現自動化部署,持續整合,持續部署等功能,本文就 Java 操作 git 相關的許可權驗證進行實踐總結.

工具

使用的工具為eclipsejgit,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.這段邏輯在JschConfigSessionFactorycreateDefaultJSch方法中,感興趣的同學可以自行檢視原始碼.

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,並且addIdentitysetKnownHosts都要使用記憶體中的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;
            }

        }
    };

}
複製程式碼

後記

總之,工具並不難,本文主要涉及到公鑰私鑰驗證的原理相關,搞懂了原理,進行操作就不難了.

相關文章