USERAUTH 使用 JGit 为 PullCommand() 安全地访问 git repo 失败

Posted

技术标签:

【中文标题】USERAUTH 使用 JGit 为 PullCommand() 安全地访问 git repo 失败【英文标题】:USERAUTH fail using JGit to access git repo securely for PullCommand() 【发布时间】:2018-02-03 23:19:30 【问题描述】:

我正在尝试使用 JGit 的 API 和以下代码进行 git pull

public class gitHubTest 
    JSch jsch = new JSch();

    // Defining the private key file location explicitly
    String userHome = System.getProperty("user.home");
    String privateKey = userHome + "/.ssh/id_rsa";
    String knownHostsFile = userHome + "/.ssh/known_hosts";
    Repository localRepo = new FileRepository("/LocalPath/.git");

    public gitHubTest() throws Exception 
        jsch.setConfig("StrictHostKeyChecking", "no");
        jsch.setKnownHosts(knownHostsFile);
        jsch.addIdentity(privateKey);
        System.out.println("privateKey :" + privateKey);
        Git git = new Git(localRepo);
        PullCommand pullcmd = git.pull();
        pullcmd.call();
    

错误堆栈跟踪:

org.eclipse.jgit.api.errors.TransportException: git@github.example.com:remote.git: USERAUTH fail
at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:245)
at org.eclipse.jgit.api.PullCommand.call(PullCommand.java:288)
at gitHubTest.<init>(gitHubTest.java:47)
at WebhooksServer.main(WebhooksServer.java:13)
Caused by: org.eclipse.jgit.errors.TransportException: git@github.example.com:remote.git: USERAUTH fail
at org.eclipse.jgit.transport.JschConfigSessionFactory.getSession(JschConfigSessionFactory.java:160)
at org.eclipse.jgit.transport.SshTransport.getSession(SshTransport.java:137)
at org.eclipse.jgit.transport.TransportGitSsh$SshFetchConnection.<init>(TransportGitSsh.java:274)
at org.eclipse.jgit.transport.TransportGitSsh.openFetch(TransportGitSsh.java:169)
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:1236)
at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:234)
... 3 more

Caused by: com.jcraft.jsch.JSchException: USERAUTH fail
at com.jcraft.jsch.UserAuthPublicKey.start(UserAuthPublicKey.java:119)
at com.jcraft.jsch.Session.connect(Session.java:470)
at org.eclipse.jgit.transport.JschConfigSessionFactory.getSession(JschConfigSessionFactory.java:117)
... 10 more

我检查过的一些建议表明,我们需要实例化 JschConfigSessionFactory,然后覆盖 configure() 方法以传递密码。我已经尝试过这样做。然后它显示一个错误。我提到了http://www.codeaffine.com/2014/12/09/jgit-authentication/,它读起来恰到好处,但不适用于我的 PullCommand。

有人可以帮忙吗?我已经在这里阅读并尝试了很多帖子,但没有一个能准确解决我的问题。

使用 configure() 方法的代码实现:

public class gitHubTest 
JSch jsch = new JSch();
String userHome = System.getProperty("user.home");
String privateKey = userHome + "/.ssh/id_rsa";
String knownHostsFile = userHome + "/.ssh/known_hosts";

public gitHubTest() throws IOException, JSchException, GitAPIException 
    Repository localRepo = new FileRepository("/LocalPath/branch.git");
    final String remoteURL = "git@github.example.com:remote.git";
    JSch.setConfig("StrictHostKeyChecking", "no");
    jsch.setKnownHosts(knownHostsFile);
    jsch.addIdentity(privateKey);
    JschConfigSessionFactory sessionFactory = new JschConfigSessionFactory() 
    @Override
    protected void configure(OpenSshConfig.Host host, Session session) 
        CredentialsProvider cp = new CredentialsProvider() 
            @Override
            public boolean isInteractive() 
                return false;
            
            @Override
            public boolean supports(CredentialItem... credentialItems) 
                return false;
            
            @Override
            public boolean get(URIish urIish, CredentialItem... credentialItems) throws UnsupportedCredentialItem 
                return false;
            
        ;
        UserInfo userInfo = new CredentialsProviderUserInfo(session,cp);
        session.setUserInfo(userInfo);
    
    ;
SshSessionFactory.setInstance(sessionFactory);
Git git = new Git(localRepo);
PullCommand pullcmd = git.pull();
pullcmd.call();

这给出了同样的错误。

【问题讨论】:

您是否在 CLI Git 中尝试过相同的操作?那里的结果是什么? jsch 在哪里声明,它如何与PullCommand 交互?您似乎尝试将 git 协议与 SSH 身份验证一起使用,这如何结合在一起?代码 sn-p 不会覆盖 configure(),请发布一个最小但完整的 sn-p 以重现问题。 @RüdigerHerrmann 感谢您的回复。我在下面的答案中发布了代码 sn-p。 你需要清楚服务器期望什么形式的协议和身份验证。您使用的是 GitHub(私有、公共、内部部署)吗? Git 服务器的不同之处在于 URL 中用户名的表示位置。再次尝试使用 CLI Git 进行相同的操作。顺便说一句,您的 CredentialsProvider 实现不会返回任何有用的东西。如果它被实际调用(使用你的调试器),它可能是身份验证失败的原因。 我使用的是私有 GitHub。您能否将我重定向到使用基于默认私钥的身份验证的示例代码 ~/.ssh.id_rsa 。 【参考方案1】:

我可以弄清楚我面临的一些问题。解决方法如下:

    如果必须在没有密码的情况下进行身份验证,则生成没有密码的 id_rsa

    我们需要在 SshSessionfactory 的配置中使用 addIdentity 覆盖 getJSch(final OpenSshConfig.Host hc, FS fs)

    SshSessionFactory sshSessionFactory = new JschConfigSessionFactory() 
        @Override
        protected void configure(OpenSshConfig.Host host, Session sess ion) 
            session.setConfig("StrictHostKeyChecking", "no");
        
    
        @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;
        
    ;
    

    我们需要调用需要不同的实例化:

    PullCommand pull = git.pull().setTransportConfigCallback(new TransportConfigCallback() 
    
        @Override
        public void configure(Transport transport) 
            SshTransport sshTransport = (SshTransport) transport;
            sshTransport.setSshSessionFactory(sshSessionFactory);
        
    );
    

然后调用pull实例:

PullResult pullResult = pull.call();

我希望这会有所帮助。

【讨论】:

很高兴您找到了解决方案。请编辑您的答案以获得更好的可读性,以便对其他人有用

以上是关于USERAUTH 使用 JGit 为 PullCommand() 安全地访问 git repo 失败的主要内容,如果未能解决你的问题,请参考以下文章

net.schmizz.sshj.userauth.UserAuthException:用尽可用的身份验证方法

使用 JGit 从 Git 存储库中查看特定修订

在 Eclipse git 中使用本机 git 而不是 jgit?

USERAUTH 因 Github 和 Spring 云配置的私钥文件而失败

使用 JGit 中止合并

git学习之jgit