您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關如何解決線上Https請求報錯的問題,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
我們系統依賴一個外部查詢接口,是HTTPS提供服務的,由于外部系統沒有測試環境,所以我們都是直接請求的他們生產環境。項目里面我們使用的HttpClient,其創建SSLClient的代碼如下:
private static CloseableHttpClient createSSLClientDefault() { SSLContext sslContext;
try {
sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
//信任所有
@Override
public boolean isTrusted(X509Certificate[] xcs, String string) {
return true;
}
}).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
return HttpClients.custom().setSSLSocketFactory(sslsf).build();
} catch (Exception ex) {
logger.error(ex.getMessage(), ex);
}
return HttpClients.createDefault();
}
這樣就可以正常的調用HTTPS服務了。但是當我們的服務部署到線上環境以后,由于生產機器找不到外部接口的域名,所以配置了host,指向該外部接口所在的Nginx服務器,但是請求一直報錯:doesn't match any of the subject alternative names: []
。用curl -k
調用該接口,報(35) SSL connect error
錯誤,當初還一度懷疑linux機器openssl版本問題,所以強制升級了一個版本還是沒有解決。后面知道curl有個-v
的參數,錯誤信息如下:
* Initializing NSS with certpath: sql:/etc/pki/nssdb* CAfile: /etc/pki/tls/certs/ca-bundle.crt CApath: none* NSS error -5990* Closing connection #0* SSL connect errorcurl: (35) SSL connect error
所以按照網上的流程升級了一下nss版本,最終curl -k可以調通服務了。但是通過httpclient還是報錯,所以可以排除掉openssl的問題。所以只能分析下測試環境和生產環境的差異,看問題到底出現在什么地方。
后面通過咨詢外部接口的同事,了解到他們的外部接口服務接入了公司內部的智能網關,在智能網關配置了統一的HTTPS證書。而且只要接入了智能網關的服務,請求都會先經過智能網關,然后轉發到他們自己的服務器。但是生產環境和智能網關不在同一網絡,而且解析不到外部接口的域名,只能通過host映射到他們的Nginx服務器上。看一下測試環境請求外部接口的網絡拓撲:
測試環境請求網絡拓撲
生產環境的請求網絡拓撲:
生產環境請求網絡拓撲
總算有點眉目了,測試環境能調通主要是能在內部DNS服務器解析到對應域名。而生產環境是通過host來做的映射,當去解析域名的時候發現當前網絡沒有該域名,所以報錯doesn't match any of the subject alternative names: []
。當時有兩種思路,第一種:能不能在生產環境開啟訪問智能網關的權限,然后直接走域名,但是公司不知道基于什么考慮,不允許這樣做。第二種:http client是否支持不解析域名的操作,確實http client可以設置不解析host的策略,將其創建SSLClient的代碼調整為如下代碼:
private static CloseableHttpClient createSSLClientDefault() { try {
SSLContextBuilder builder = new SSLContextBuilder();
builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
//不進行主機名驗證
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(builder.build(),
NoopHostnameVerifier.INSTANCE);
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", new PlainConnectionSocketFactory())
.register("https", sslConnectionSocketFactory)
.build();
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
cm.setMaxTotal(100);
CloseableHttpClient httpclient = HttpClients.custom()
.setSSLSocketFactory(sslConnectionSocketFactory)
.setDefaultCookieStore(new BasicCookieStore())
.setConnectionManager(cm).build();
return httpclient;
} catch (Exception e) {
logger.error("createSSLClientDefault error", e);
}
return null;
}
即可解決問題。一個https的小問題確實耗費了我不少的時間,記錄一下。
以上就是如何解決線上Https請求報錯的問題,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。