Ale*_*ros 7 java ssl okhttp spring-boot
我有一个使用 okhttp3 的 spring-boot 应用程序(版本 2.3.7),我试图在https://test.server.com:8888/api. 服务器上的证书是自签名的,因此我已更新我的插入符以信任此证书。当我像这样运行 SSLPoke.class 时,java SSLPoke test.server.com 8888我得到了Successfully Connected。但是当我的应用程序发出请求时,我收到错误javax.net.ssl.SSLPeerUnverifiedException: Hostname test.server.com not verified:。由于 cacerts 已更新,我是否需要编写额外的代码来验证主机名?
更具体地说,我有以下片段。如果我在虚拟机选项中传递信任库,-Djavax.net.ssl.trustStore=client-truststore.jks -Djavax.net.ssl.trustStorePassword=changeit则使用 okhttp 的调用会失败,但使用其余模板会成功。
@SpringBootApplication
public class DemoOkhttpClientApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(DemoOkhttpClientApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
try {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://localhost:8443/")
.addConverterFactory(MoshiConverterFactory.create())
.build();
TestClient testClient = retrofit.create(TestClient.class);
System.out.println(String.format("OkHttp Response %s", testClient.callTestEndpoint().execute().body()));
} catch (Exception ex){
System.err.println();
System.err.println("Ok Http error " + ex.getMessage());
}
try {
RestTemplate restTemplate = new RestTemplate();
System.out.println(String.format("Rest Template Response %s",
restTemplate.exchange("https://localhost:8443/test", HttpMethod.GET, null, String.class)));
} catch (Exception ex){
System.err.println("Rest Template error" + ex.getMessage());
}
}
}
interface TestClient {
@GET("/test")
Call<String> callTestEndpoint();
}
Run Code Online (Sandbox Code Playgroud)
上面代码片段的输出是这样的
Ok Http error Hostname localhost not verified:
certificate: sha256/INkKXJiMFIGNnvE5ga1Ye0KjxjP5jO9hIrNvQs4wuU0=
DN: CN=localhost, OU=PC, O=PC, L=Marousi, ST=Athens, C=GR
subjectAltNames: []
Rest Template Response <200,Ok,[Content-Type:"text/plain;charset=UTF-8", Content-Length:"2", Date:"Thu, 11 Feb 2021 17:09:55 GMT", Keep-Alive:"timeout=60", Connection:"keep-alive"]>
Run Code Online (Sandbox Code Playgroud)
我怀疑这是因为您生成了无效的证书,CN 不应再用于主机名验证。您的证书中的 subjectAltNames 为空。这在 3.10.0 中发生了变化
\nhttps://square.github.io/okhttp/changelog_3x/#version-3100
\n\n\n新增内容:Don\xe2\x80\x99t 回退到主机名的通用名称 (CN) 验证。此行为已于 2000 年 5 月随 RFC 2818 弃用,并且最近已从主要 Web 浏览器中删除。
\n
如果您只想将一台开发服务器列入白名单,您可以使用以下命令
\nhttps://square.github.io/okhttp/changelog/#version-470
\nval clientCertificates = HandshakeCertificates.Builder()\n .addPlatformTrustedCertificates()\n .addInsecureHost("localhost")\n .build()\n\nval client = OkHttpClient.Builder()\n .sslSocketFactory(clientCertificates.sslSocketFactory(), clientCertificates.trustManager)\n .build()\nRun Code Online (Sandbox Code Playgroud)\n
显然唯一的方法是让 OkHttp 忽略主机名验证
OkHttpClient okHttpClient = new OkHttpClient.Builder().hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
}).build();
Retrofit retrofit = new Retrofit.Builder()
.client(okHttpClient)
.baseUrl("https://localhost:8443/")
.addConverterFactory(MoshiConverterFactory.create())
.build();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10862 次 |
| 最近记录: |