为 JGit 克隆命令关闭 SSL 验证
Turn SSL verification off for JGit clone command
我正在尝试通过 CloneCommand
克隆 Git 存储库。
有了这段代码
`Git.cloneRepository().setDirectory(new File(path)).setURI(url).call();`
远程存储库位于使用自签名证书的 GitBlit 实例上。
由于这些自签名证书,我在执行克隆的获取部分时遇到以下异常:
Caused by: java.security.cert.CertificateException: No name matching <hostName> found
at sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:221)
at sun.security.util.HostnameChecker.match(HostnameChecker.java:95)
虽然我可以创建一个新的 TrustManager
,但注册一个虚拟 HostnameVerifier
并创建并初始化一个使用该虚拟 TrustManager
的 SSLContext
。
克隆完成后恢复所有这些。
然而,这意味着在同一时间启动的任何其他 SSL 连接会将它们暴露给不安全的连接。
在已经克隆的 repo 上,您可以将 http.sslVerify 设置为 false 并且 JGit 工作得很好。
有没有更简洁的方法让我告诉 JGit 将这个 http.sslVerify 设置为 false 以进行克隆操作,就像我可以为已经克隆的存储库做的那样。
在 4.9 版本中,JGit 将更优雅地处理 SSL 验证。如果SSL
握手不成功,JGit 将询问 CredentialsProvider
是否应跳过 SSL 验证。
在此过程中,CredentialsProvider
会得到一个 InformationalMessage
文本描述问题,最多三个 YesNoType
CredentialItem
来决定是否跳过 SSL 验证此操作,对于当前存储库,and/or always.
似乎做出更改时考虑了交互式 UI,可能很难以编程方式回答这些 'credential requests'。 commit message of this change 更详细地描述了行为。
如果您确定 SSL 验证是唯一将被发送的 InformationalMessage
,您可以应用伴随更改的 this test 中使用的技术并盲目回答 'yes'所有这些问题。
对于较早版本的 JGit,或者如果 CredentialsProvider
模型不符合您的需求,有两种解决方法如下所述。
要解决此限制,您可以手动执行特定的克隆步骤,如以下评论中所建议:
- 使用 InitCommand 初始化存储库
- 将 ssl 验证设置为 false
StoredConfig config = git.getRepository().getConfig();
config.setBoolean( "http", null, "sslVerify", false );
config.save();
- 获取(参见 FetchCommand)
- 结帐(请参阅 CheckoutCommand)
解决此问题的另一种方法是 提供一个 HttpConnectionFactory
returns HttpConnection
具有虚拟主机名和证书验证程序.例如:
class InsecureHttpConnectionFactory implements HttpConnectionFactory {
@Override
public HttpConnection create( URL url ) throws IOException {
return create( url, null );
}
@Override
public HttpConnection create( URL url, Proxy proxy ) throws IOException {
HttpConnection connection = new JDKHttpConnectionFactory().create( url, proxy );
HttpSupport.disableSslVerify( connection );
return connection;
}
}
HttpConnection
在包 org.eclipse.jgit.transport.http
中并且是 HTTP 连接的 JGit 抽象。虽然该示例使用默认实现(由 JDK http 代码支持),但您可以自由使用自己的实现或使用 Apache http 组件的 org.eclipse.jgit.transport.http.apache
包提供的实现。
当前使用的连接工厂可以用HttpTransport::setConnectionFactory()
更改:
HttpConnectionFactory preservedConnectionFactory = HttpTransport.getConnectionFactory();
HttpTransport.setConnectionFactory( new InsecureHttpConnectionFactory() );
// clone repository
HttpTransport.setConnectionFactory( preservedConnectionFactory );
不幸的是,连接工厂是一个单例,因此当 JGit 命令并发执行时,这个技巧需要额外的工作(例如,一个线程局部变量来控制 sslVerify 是打开还是关闭)。
另一种解决方法是在调用 Git.cloneRepository()
:
之前在当前用户的家中创建一个 .gitconfig
文件
File file = new File(System.getProperty("user.home")+"/.gitconfig");
if(!file.exists()) {
PrintWriter writer = new PrintWriter(file);
writer.println("[http]");
writer.println("sslverify = false");
writer.close();
}
这将使 JGit 跳过 SSL 证书验证。
我已经从上面的所有答案中推断出下面的片段;
private void disableSSLVerify(URI gitServer) throws Exception {
if (gitServer.getScheme().equals("https")) {
FileBasedConfig config = SystemReader.getInstance().openUserConfig(null, FS.DETECTED);
synchronized (config) {
config.load();
config.setBoolean(
"http",
"https://" + gitServer.getHost() + ':' + (gitServer.getPort() == -1 ? 443 : gitServer.getPort()),
"sslVerify", false);
config.save();
}
}
}
此选项更安全,因为它允许单独 gitServer
的 sslVerify 为 false。
请看一下这个 link 与其他 options 共享。
我遇到了同样的问题,我使用 ChainingCredentialsProvider
class 创建了一个凭证提供程序,我的实现如下所示,
请注意,这是对先前给出的答案的实施。
CredentialsProvider token = new UsernamePasswordCredentialsProvider("PRIVATE-TOKEN", token);
CredentialsProvider ssl = new CredentialsProvider() {
@Override
public boolean supports(CredentialItem... items) {
for ( CredentialItem item : items ) {
if ( (item instanceof CredentialItem.YesNoType) ) {
return true;
}
}
return false;
}
@Override
public boolean get(URIish uri, CredentialItem... items) throws UnsupportedCredentialItem {
for ( CredentialItem item : items ) {
if ( item instanceof CredentialItem.YesNoType ) {
(( CredentialItem.YesNoType ) item).setValue(true);
return true;
}
}
return false;
}
@Override
public boolean isInteractive() {
return false;
}
};
CredentialsProvider cp = new ChainingCredentialsProvider(ssl, token);
Git result = Git.cloneRepository()
.setURI(gitProjectUrl)
.setDirectory(localPath)
.setCredentialsProvider(cp)
.call();
我正在尝试通过 CloneCommand
克隆 Git 存储库。
有了这段代码
`Git.cloneRepository().setDirectory(new File(path)).setURI(url).call();`
远程存储库位于使用自签名证书的 GitBlit 实例上。 由于这些自签名证书,我在执行克隆的获取部分时遇到以下异常:
Caused by: java.security.cert.CertificateException: No name matching <hostName> found
at sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:221)
at sun.security.util.HostnameChecker.match(HostnameChecker.java:95)
虽然我可以创建一个新的 TrustManager
,但注册一个虚拟 HostnameVerifier
并创建并初始化一个使用该虚拟 TrustManager
的 SSLContext
。
克隆完成后恢复所有这些。
然而,这意味着在同一时间启动的任何其他 SSL 连接会将它们暴露给不安全的连接。
在已经克隆的 repo 上,您可以将 http.sslVerify 设置为 false 并且 JGit 工作得很好。
有没有更简洁的方法让我告诉 JGit 将这个 http.sslVerify 设置为 false 以进行克隆操作,就像我可以为已经克隆的存储库做的那样。
在 4.9 版本中,JGit 将更优雅地处理 SSL 验证。如果SSL
握手不成功,JGit 将询问 CredentialsProvider
是否应跳过 SSL 验证。
在此过程中,CredentialsProvider
会得到一个 InformationalMessage
文本描述问题,最多三个 YesNoType
CredentialItem
来决定是否跳过 SSL 验证此操作,对于当前存储库,and/or always.
似乎做出更改时考虑了交互式 UI,可能很难以编程方式回答这些 'credential requests'。 commit message of this change 更详细地描述了行为。
如果您确定 SSL 验证是唯一将被发送的 InformationalMessage
,您可以应用伴随更改的 this test 中使用的技术并盲目回答 'yes'所有这些问题。
对于较早版本的 JGit,或者如果 CredentialsProvider
模型不符合您的需求,有两种解决方法如下所述。
要解决此限制,您可以手动执行特定的克隆步骤,如以下评论中所建议:
- 使用 InitCommand 初始化存储库
- 将 ssl 验证设置为 false
StoredConfig config = git.getRepository().getConfig();
config.setBoolean( "http", null, "sslVerify", false );
config.save();
- 获取(参见 FetchCommand)
- 结帐(请参阅 CheckoutCommand)
解决此问题的另一种方法是 提供一个 HttpConnectionFactory
returns HttpConnection
具有虚拟主机名和证书验证程序.例如:
class InsecureHttpConnectionFactory implements HttpConnectionFactory {
@Override
public HttpConnection create( URL url ) throws IOException {
return create( url, null );
}
@Override
public HttpConnection create( URL url, Proxy proxy ) throws IOException {
HttpConnection connection = new JDKHttpConnectionFactory().create( url, proxy );
HttpSupport.disableSslVerify( connection );
return connection;
}
}
HttpConnection
在包 org.eclipse.jgit.transport.http
中并且是 HTTP 连接的 JGit 抽象。虽然该示例使用默认实现(由 JDK http 代码支持),但您可以自由使用自己的实现或使用 Apache http 组件的 org.eclipse.jgit.transport.http.apache
包提供的实现。
当前使用的连接工厂可以用HttpTransport::setConnectionFactory()
更改:
HttpConnectionFactory preservedConnectionFactory = HttpTransport.getConnectionFactory();
HttpTransport.setConnectionFactory( new InsecureHttpConnectionFactory() );
// clone repository
HttpTransport.setConnectionFactory( preservedConnectionFactory );
不幸的是,连接工厂是一个单例,因此当 JGit 命令并发执行时,这个技巧需要额外的工作(例如,一个线程局部变量来控制 sslVerify 是打开还是关闭)。
另一种解决方法是在调用 Git.cloneRepository()
:
.gitconfig
文件
File file = new File(System.getProperty("user.home")+"/.gitconfig");
if(!file.exists()) {
PrintWriter writer = new PrintWriter(file);
writer.println("[http]");
writer.println("sslverify = false");
writer.close();
}
这将使 JGit 跳过 SSL 证书验证。
我已经从上面的所有答案中推断出下面的片段;
private void disableSSLVerify(URI gitServer) throws Exception {
if (gitServer.getScheme().equals("https")) {
FileBasedConfig config = SystemReader.getInstance().openUserConfig(null, FS.DETECTED);
synchronized (config) {
config.load();
config.setBoolean(
"http",
"https://" + gitServer.getHost() + ':' + (gitServer.getPort() == -1 ? 443 : gitServer.getPort()),
"sslVerify", false);
config.save();
}
}
}
此选项更安全,因为它允许单独 gitServer
的 sslVerify 为 false。
请看一下这个 link 与其他 options 共享。
我遇到了同样的问题,我使用 ChainingCredentialsProvider
class 创建了一个凭证提供程序,我的实现如下所示,
请注意,这是对先前给出的答案的实施。
CredentialsProvider token = new UsernamePasswordCredentialsProvider("PRIVATE-TOKEN", token);
CredentialsProvider ssl = new CredentialsProvider() {
@Override
public boolean supports(CredentialItem... items) {
for ( CredentialItem item : items ) {
if ( (item instanceof CredentialItem.YesNoType) ) {
return true;
}
}
return false;
}
@Override
public boolean get(URIish uri, CredentialItem... items) throws UnsupportedCredentialItem {
for ( CredentialItem item : items ) {
if ( item instanceof CredentialItem.YesNoType ) {
(( CredentialItem.YesNoType ) item).setValue(true);
return true;
}
}
return false;
}
@Override
public boolean isInteractive() {
return false;
}
};
CredentialsProvider cp = new ChainingCredentialsProvider(ssl, token);
Git result = Git.cloneRepository()
.setURI(gitProjectUrl)
.setDirectory(localPath)
.setCredentialsProvider(cp)
.call();