我正在尝试让一个嵌入式的 Spring 配置服务器实现从 GitHub 读取配置。 我正在遵循本教程:
https://mromeh.com/2017/12/04/spring-boot-with-embedded-config-server-via-spring-cloud-config/
当我的 Spring 启动应用程序尝试启动时,我收到以下异常:
由以下原因引起:com.jcraft.jsch.JSchException:没有任何可用的 密码。 在com.jcraft.jsch.Session.send_kexinit(会话.java:629) at com.jcraft.jsch.Session.connect(Session.java:307) at org.eclipse.jgit.transport.JschConfigSessionFactory.getSession(JschConfigSessionFactory.java:146) ...还有 23 个
在我的代码中看到唯一有趣的部分是我的bootstrap.yml
文件,它看起来像这样:
spring:
application:
name: DemoApplication.yml
---
spring:
cloud:
config:
failFast: true
server:
bootstrap: true
git:
uri: git@github.com:mycompany/demo-config.git
我正在MacOS上运行OpenJDK 8 v212,运行以下内容:
#> java -version
openjdk version "1.8.0_212"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_212-b03)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.212-b03, mixed mode)
我已经搜索了 Spring 代码和文档,还没有找到任何关于传递配置参数或添加代码来影响 Spring 使用的 Jsch 会话的构造方式的信息。 我发现的一切都表明我正在做的事情应该奏效。
我不知道该何去何从。 有人可以告诉我我错过了什么...我需要做什么来解决这个问题?
要合并前面的评论...
在幕后,Spring正在使用JGit进行SSH连接。 默认情况下,这使用 JSch 建立由~/.ssh/config
文件配置的 SSH 连接。
维基还详细介绍了如何绕过JSch并使用本机ssh
命令,可以设置GIT_SSH
环境变量,例如在OS X或Linux中/usr/bin/ssh
,甚至类似于C:Program FilesTortoiseGitbinTortoiseGitPlink.exe
。
在有关如何避免依赖于设置环境变量的注释之后,请注意如何使用 TransportGitSsh.useExtSession() 方法中的SystemReader
检查GIT_SSH
环境变量。
这意味着一种方法是覆盖SystemReader
类。 不过,这不是一个小接口,因此会涉及相当多的包装代码 - 自定义位在getenv()
:
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.SystemReader;
public class CustomSystemReader extends SystemReader {
private final SystemReader systemReader;
public CustomSystemReader(SystemReader systemReader) {
this.systemReader = systemReader;
}
@Override
public String getHostname() {
return systemReader.getHostname();
}
@Override
public String getenv(String variable) {
if ("GIT_SSH".equals(variable))
return "/usr/bin/ssh";
return systemReader.getenv(variable);
}
@Override
public String getProperty(String key) {
return systemReader.getProperty(key);
}
@Override
public FileBasedConfig openUserConfig(Config parent, FS fs) {
return systemReader.openUserConfig(parent, fs);
}
@Override
public FileBasedConfig openSystemConfig(Config parent, FS fs) {
return systemReader.openSystemConfig(parent, fs);
}
@Override
public long getCurrentTime() {
return systemReader.getCurrentTime();
}
@Override
public int getTimezone(long when) {
return systemReader.getTimezone(when);
}
}
然后可以像这样连接:
SystemReader.setInstance(
new CustomSystemReader(SystemReader.getInstance()));
@df778899给了我解决这个问题所需的方向,并声明
如您所发现的,默认情况下,它使用 JSch,它由 ~/.ssh/config 文件 - 如果存在,您可能会在其中找到线索。
我已经从这个文件中寻找线索,特别是寻找有关加密设置的任何内容。 我看到我在文件顶部附近有这个注释掉的行:
# Ciphers +aes256-cbc
我错过了什么(我以为我已经对"密码"进行了文本搜索,但显然,我没有)是埋在文件中间的一堆不相关的设置中,我再次做同样的事情,这次没有注释掉:
Host *
...
Ciphers +aes256-cbc
...
正是这句台词杀死了我和Jsch。 如果我注释掉这一行,我的简单设置工作正常。 @df778899关于~/.ssh/config
对Jsch的设置至关重要的声明是我需要的推动力。
这不会成为我解决方案的一部分,但我要指出的是,以下代码似乎是我在 Java 中设置GIT_SSH
的方式,在我的main()
顶部:
public static void main(String[] args) {
try {
Map<String, String> env = System.getenv();
Field field = env.getClass().getDeclaredField("m");
field.setAccessible(true);
((Map<String, String>) field.get(env)).put("GIT_SSH", "/usr/bin/ssh");
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
SpringApplication.run(DemoApplication.class, args);
}
这也"解决"了我的问题。 关于getDeclaredField("m")
的那一点特别奇怪。 "m"到底是什么?