jgit
JGit中的身份验证与本地Git大致相同。 支持SSH和HTTP(S)等常用协议及其身份验证方法。 本文总结了如何使用JGit身份验证API安全地访问远程Git存储库。
尽管本文中的示例使用CloneCommand,但是可以将所描述的技术应用于连接到远程存储库的所有类,例如FetchCommand,PushCommand,LsRemoteCommand等。所有这些命令都有一个公共基类-TransportCommand-提供了所讨论的方法这里。
HTTP(S)– https://example.com/repo.git
通过HTTP和HTTPS进行身份验证非常简单。 当命令请求身份验证凭据时,将使用CredentialsProvider的实现返回身份验证凭据。 可以通过setCredentialsProvider()指定用于特定命令的CredentialsProvider。
例如,以下代码通过HTTPS克隆存储库,并使用用户名和密码进行身份验证。
CloneCommand cloneCommand = Git.cloneRepository();
cloneCommand.setURI( "https://example.com/repo.git" );
cloneCommand.setCredentialsProvider( new UsernamePasswordCredentialsProvider( "user", "password" ) );
UsernamePasswordCredentialsProvider是JGit随附的CredentialsProvider的实现,并使用给定的用户名和密码进行身份验证。
另外,JGit(3.5版和更高版本)也可以从用户的.netrc文件中读取凭据。 NetRCCredentialsProvider使用文件中的第一个机器条目进行身份验证。
尽管不建议通过不安全的连接发送凭据,但是所描述的方法也适用于纯HTTP,例如http://example.com/repo.git。
带有公钥的SSH – ssh://user@example.com/repo.git
JGit委托创建和销毁与抽象SshSessionFactory的SSH连接。 要将公共密钥身份验证用于SSH连接,必须为执行的命令指定这样的会话工厂。
使用setTransportConfigCallback(),可以指定TransportConfigCallback接口以拦截连接过程。 建立连接之前,将调用唯一的方法configure()。 传递给它一个传输类型的参数,该参数将用于在本地和远程存储库之间复制对象。 对于每个协议,都有一个不同的Transport子类来处理该协议的各个详细信息。
如下所示,该回调可用于在使用前立即配置Transport实例:
SshSessionFactory sshSessionFactory = new JschConfigSessionFactory() {
@Override
protected void configure( Host host, Session session ) {
// do nothing
}
};
CloneCommand cloneCommand = Git.cloneRepository();
cloneCommand.setURI( "ssh://user@example.com/repo.git" );
cloneCommand.setTransportConfigCallback( new TransportConfigCallback() {
@Override
public void configure( Transport transport ) {
SshTransport sshTransport = ( SshTransport )transport;
sshTransport.setSshSessionFactory( sshSessionFactory );
}
} );
JGit提供了一个抽象的JSchConfigSessionFactory,它使用JSch建立SSH连接,并要求覆盖它的configure()。 因为在最简单的情况下没有任何要配置的内容,所以上面的示例只是覆盖了使代码编译的方法。
JSchConfigSessionFactory大多数与本机Git使用的SSH实现OpenSSH兼容。 它从用户的.ssh目录中的默认主机(身份,id_rsa和id_dsa)的默认位置加载已知主机和私钥。
如果您的私钥文件的名称不同或位于其他位置,则建议覆盖createDefaultJSch()。 调用基本方法后,可以像这样添加自定义私钥:
@Override
protected JSch createDefaultJSch( FS fs ) throws JSchException {
JSch defaultJSch = super.createDefaultJSch( fs );
defaultJSch.addIdentity( "/path/to/private_key" )
return defaultJSch;
}
在此示例中,添加了来自自定义文件位置的私钥。 如果您查看JSch JavaDoc ,将会发现更多重载的addIdentity()方法。
为了完整起见,我应该提到还有一个全球会话工厂。 可以通过SshSessionFactory.get / setInstance()获取和更改它,并且如果没有为命令配置特定的shSessionFactory,它将用作默认值。 但是,我建议不要使用它。 除了使编写独立的测试变得更加困难之外,您的控件之外可能还有一些代码会更改全局会话工厂。
SSH和密码– ssh://user@example.com/repo.git
与通过公用密钥使用SSH一样,必须指定SshSessionFactory以使用受密码保护的SSH连接。 但是这次,会话工厂的configure()方法是有目的的。
SshSessionFactory sshSessionFactory = new JschConfigSessionFactory() {
@Override
protected void configure( Host host, Session session ) {
session.setPassword( "password" );
}
} );
CloneCommand cloneCommand = Git.cloneRepository();
cloneCommand.setURI( "ssh://user@example.com/repo.git" );
cloneCommand.setTransportConfigCallback( new TransportConfigCallback() {
@Override
public void configure( Transport transport ) {
SshTransport sshTransport = ( SshTransport )transport;
sshTransport.setSshSessionFactory( sshSessionFactory );
}
} );
JSch会话表示与SSH服务器的连接,在第4行中,设置了当前会话的密码。 其余代码与用于通过SSH与公共密钥身份验证进行连接的代码相同。
使用哪种身份验证方法?
此处讨论的某些身份验证方法也可以组合使用。 例如,在尝试通过带有公共密钥的SSH连接到远程存储库时设置凭据提供者不会有任何危害。 但是,您通常希望事先知道给定的存储库URL将使用哪种传输。
为了确定这一点,可以使用TransportProtocol的canHandle()方法。 如果协议可以处理给定的URL,则返回true,否则返回false。 可以从Transport.getTransportProtocols()获得所有已注册TransportProtocol的列表。 一旦知道了协议,就可以选择适当的身份验证方法。
验证@ GitHub
GitHub支持多种协议和身份验证方法,但肯定不是所有可能的组合。 例如,一个常见的错误是尝试将SSH与密码验证一起使用。 但是不支持此组合-仅支持带公钥的SSH。
GitHub提供的协议的比较列出了支持的内容和不支持的内容。 总结一下,有:
- Plain Git(例如git://github.com/user/repo.git):传输未加密,服务器未通过验证。
- HTTPS(例如https://github.com/user/repo.git):实际上可在任何地方使用。 使用密码身份验证进行推送,但允许匿名获取和克隆。
- SSH(例如ssh://git@github.com:user / repo.git):使用公钥身份验证,也用于获取和克隆。
结束JGit身份验证
虽然我发现身份验证功能在JGit API上散布了很多,但它们可以完成任务。 此处给出的食谱有望为您提供必要的基础知识,以验证JGit中的连接,并且隐藏API的复杂性可以视为练习干净代码的练习!
如果您有困难或问题,请随时发表评论或向友好而乐于助人的JGit社区寻求帮助。
翻译自: https://www.javacodegeeks.com/2014/12/jgit-authentication-explained.html
jgit