使用 JGit 的密钥安全地访问 Git 存储库

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13686643/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 07:51:14  来源:igfitidea点击:

Using Keys with JGit to Access a Git Repository Securely

javagitsshjschjgit

提问by Izza

I'm using JGitto access a remote Git repo, and I need to use SSHfor it. JGit uses JSchto provide secure access. However, I'm not sure how to set the key file and the knows hosts file for JGit. What I have tried is as follows.

我正在使用JGit访问远程 Git 存储库,我需要为此使用SSH。JGit 使用JSch来提供安全访问。但是,我不确定如何为 JGit 设置密钥文件和知道主机文件。我尝试过的内容如下。

Created a custom configuration of the SshSessionFactory, using by subclassing JSchConfigSessionFactory:

创建SshSessionFactory的自定义配置,通过子类化JSchConfigSessionFactory 使用

public class CustomJschConfigSessionFactory extends JschConfigSessionFactory {
    @Override
    protected void configure(OpenSshConfig.Host host, Session session) {
        session.setConfig("StrictHostKeyChecking", "yes");
    }
}

In the class which I access the remote Git repo, did the following:

在我访问远程 Git 存储库的类中,执行以下操作:

CustomJschConfigSessionFactory jschConfigSessionFactory = new CustomJschConfigSessionFactory();

JSch jsch = new JSch();
try {
    jsch.addIdentity(".ssh/id_rsa");
    jsch.setKnownHosts(".ssh/known_hosts");
} catch (JSchException e) {
    e.printStackTrace();  
}
    SshSessionFactory.setInstance(jschConfigSessionFactory);

I can't figure out how to associate this JSch object with JGit so that it can successfully connect to the remote repository. When I try to clone it with JGit, I get the following exception:

我不知道如何将这个 JSch 对象与 JGit 相关联,以便它可以成功连接到远程存储库。当我尝试使用 JGit 克隆它时,出现以下异常:

org.eclipse.jgit.api.errors.TransportException: [email protected]:abc.org/test_repo.git: reject HostKey: git.test.com
at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:137)
at org.eclipse.jgit.api.CloneCommand.fetch(CloneCommand.java:178)
at org.eclipse.jgit.api.CloneCommand.call(CloneCommand.java:125)
at GitTest.cloneRepo(GitTest.java:109)
at GitTest.main(GitTest.java:223)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: org.eclipse.jgit.errors.TransportException: [email protected]:abc.org/test_repo.git: reject HostKey: git.test.com
at org.eclipse.jgit.transport.JschConfigSessionFactory.getSession(JschConfigSessionFactory.java:142)
at org.eclipse.jgit.transport.SshTransport.getSession(SshTransport.java:121)
at org.eclipse.jgit.transport.TransportGitSsh$SshFetchConnection.<init>(TransportGitSsh.java:248)
at org.eclipse.jgit.transport.TransportGitSsh.openFetch(TransportGitSsh.java:147)
at org.eclipse.jgit.transport.FetchProcess.executeImp(FetchProcess.java:136)
at org.eclipse.jgit.transport.FetchProcess.execute(FetchProcess.java:122)
at org.eclipse.jgit.transport.Transport.fetch(Transport.java:1104)
at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:128)
... 9 more
Caused by: com.jcraft.jsch.JSchException: reject HostKey: git.test.com
at com.jcraft.jsch.Session.checkHost(Session.java:748)
at com.jcraft.jsch.Session.connect(Session.java:321)
at org.eclipse.jgit.transport.JschConfigSessionFactory.getSession(JschConfigSessionFactory.java:116)
... 16 more

I have added the git.test.com entry to my /etc/hostsfile. I have used the same code to access a git repo with a http url, so the code it working fine. It's the key handling part that is failing. Any idea on how to handle this?

我已将 git.test.com 条目添加到我的/etc/hosts文件中。我使用相同的代码来访问带有 http url 的 git repo,因此代码运行良好。这是失败的关键处理部分。关于如何处理这个的任何想法?

采纳答案by Izza

Managed to find the issue. The public key in the server side had a different name other than the usual id_rsa.pub, while the private key on my side was id_rsa. JSch expects by default the public key to have the same name as the private key plus the .pub suffix. Using a key pair with a common name (ex.: private = key_1 and public = key_1.pub) solves the issue.

设法找到了问题。服务器端的公钥与通常的 id_rsa.pub 不同,而我端的私钥是 id_rsa。默认情况下,JSch 期望公钥与私钥同名并加上 .pub 后缀。使用具有通用名称的密钥对(例如:private = key_1 和 public = key_1.pub)可以解决该问题。

回答by paulmdavies

You need to override the getJSchmethod in your custom factory class:

您需要覆盖getJSch自定义工厂类中的方法:

class CustomConfigSessionFactory extends JschConfigSessionFactory
{
    @Override
    protected JSch getJSch(final OpenSshConfig.Host hc, FS fs) throws JSchException {
        JSch jsch = super.getJSch(hc, fs);
        jsch.removeAllIdentity();
        jsch.addIdentity( "/path/to/private/key" );
        return jsch;
    }
}

Calling jsch.removeAllIdentityis important; it doesn't seem to work without it.

打电话jsch.removeAllIdentity很重要;没有它,它似乎无法工作。

A caveat: I wrote the above in Scala, and then translated it over to Java, so it might not be quite right. The original Scala is as follows:

一个警告:我在 Scala 中写了上面的内容,然后将它翻译成 Java,所以它可能不太正确。原来的Scala如下:

class CustomConfigSessionFactory extends JschConfigSessionFactory
{
    override protected def getJSch( hc : OpenSshConfig.Host, fs : FS ) : JSch =
    {
        val jsch = super.getJSch(hc, fs)
        jsch.removeAllIdentity()
        jsch.addIdentity( "/path/to/private/key" )
        jsch
    }
}

回答by joshwa

Jsch sesems to not like a known_hosts file in the hashed format-- it must conform to the format produced by:

Jsch 似乎不喜欢散列格式的 known_hosts 文件——它必须符合以下生成的格式:

ssh-keyscan -t rsa hostname >> ~/.ssh/known_hosts

ssh-keyscan -t rsa hostname >> ~/.ssh/known_hosts

e.g.

例如

<hostname> ssh-rsa <longstring/longstring>

not:

不是:

 |1|<hashed hostname>= ecdsa-sha2-nistp256 <hashed fingerprint>=