[英]Apache HttpClient Error: javax.net.ssl.SSLPeerUnverifiedException: Peer Not Authenticated
[英]Exception : javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
public HttpClientVM() {
BasicHttpParams params = new BasicHttpParams();
ConnManagerParams.setMaxTotalConnections(params, 10);
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setUseExpectContinue(params, false);
HttpConnectionParams.setStaleCheckingEnabled(params, true);
HttpConnectionParams.setConnectionTimeout(params, 30000);
HostnameVerifier hostnameVerifier=
org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http",socketFactory, 80));
schemeRegistry.register(new Scheme("https",socketFactory, 443));
ThreadSafeClientConnManager manager = new ThreadSafeClientConnManager(params, schemeRegistry);
// Set verifier
client = new DefaultHttpClient(manager, params);
}
問題:
執行client.accessURL(url)
時,出現如下錯誤:
Exception in thread "main" javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
at com.sun.net.ssl.internal.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:352)
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:128)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:397)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:495)
at org.apache.http.conn.scheme.SchemeSocketFactoryAdaptor.connectSocket(SchemeSocketFactoryAdaptor.java:62)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:148)
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:150)
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:121)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:575)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:425)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:732)
附加信息:
過期的證書是我們的“javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated”的原因。
keytool -list -v -keystore filetruststore.ts
Enter keystore password:
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
Alias name: somealias
Creation date: Jul 26, 2012
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Unknown, OU=SomeOU, O="Some Company, Inc.", L=SomeCity, ST=GA, C=US
Issuer: CN=Unknown, OU=SomeOU, O=Some Company, Inc.", L=SomeCity, ST=GA, C=US
Serial number: 5011a47b
Valid from: Thu Jul 26 16:11:39 EDT 2012 until: Wed Oct 24 16:11:39 EDT 2012
此錯誤是因為您的服務器沒有有效的 SSL 證書。 因此我們需要告訴客戶端使用不同的 TrustManager。 這是一個示例代碼:
SSLContext ctx = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
ctx.init(null, new TrustManager[]{tm}, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
ClientConnectionManager ccm = base.getConnectionManager();
SchemeRegistry sr = ccm.getSchemeRegistry();
sr.register(new Scheme("https", 443, ssf));
client = new DefaultHttpClient(ccm, base.getParams());
如果您的服務器基於 JDK 7,而您的客戶端在 JDK 6 上並使用 SSL 證書,則會出現此異常。 在 JDK 7 中 sslv2hello 消息握手默認是禁用的,而在 JDK 6 中 sslv2hello 消息握手是啟用的。 因此,當您的客戶端嘗試連接服務器時,將向服務器發送 sslv2hello 消息,並且由於 sslv2hello 消息禁用,您將收到此異常。 要解決此問題,您必須將客戶端移至 JDK 7,或者必須使用 6u91 版本的 JDK。 但是要獲得此版本的 JDK,您必須獲得 MOS(My Oracle Support)企業支持。 這個補丁不是公開的。
如果客戶端指定“https”但服務器僅運行“http”,則您可以獲得此信息。 因此,服務器不希望建立安全連接。
如果您嘗試通過 HTTPS 連接並且服務器未配置為正確處理 SSL 連接,也會發生這種情況。
我會檢查您的應用程序服務器 SSL 設置並確保證書配置正確。
就我而言,我使用的是 JDK 8 客戶端,而服務器使用的是不安全的舊密碼。 服務器是 Apache,我將此行添加到 Apache 配置中:
SSLCipherSuite ALL:!ADH:RC4+RSA:+HIGH:!MEDIUM:!LOW:!SSLv2:!EXPORT
您應該使用這樣的工具來驗證您的 SSL 配置當前是否安全: https : //www.ssllabs.com/ssltest/analyze.html
在我的例子中,服務器在 Docker 上運行(使用基礎鏡像采用 passopenjdk/openjdk11:alpine),問題是 TLS 協議級別錯誤(感謝以下頁面提供解釋: https : //jfrog.com/knowledge- base/how-to-resolve-the-javax-net-ssl-sslpeerunverifiedexception-peer-not-authenticated-error-when-using-java-11/ )。
解決方案最終是使用以下 java 標志運行客戶端:
-Djdk.tls.client.protocols=TLSv1.2
當您的 keystore.jks 文件中缺少驗證碼證書時,我們使用 VPN 時會遇到同樣的問題。
檢查您的服務器密鑰庫是否具有驗證碼證書,為此請使用以下命令。 Go 到您的 keystore.jks 位置並點擊usr/java/jdk1.7.0_91/bin/keytool -list -v -keystore keystore.jks
它將列出您在其中擁有的所有證書,其中: usr/java/jdk1.7.0_91/bin/keytool
是 java keytool 的位置,如果您不確定服務器上的 java 路徑,可以使用which java
命令。
如果它不存在,那么您必須下載驗證碼證書並將其安裝到密鑰庫,按照以下步驟進行操作:
一種。 打開: https://www.google.com/recaptcha/api/siteverify點擊secure圖標,點擊certificate is valid
b. 點擊連接是安全的
Go to the location of keystore.jks :
Run this command :
/usr/java/jdk1.7.0_91/bin/keytool -import -alias googlecaptcha -keystore "/location/to/the/keystore.jks" -file "/location/to/crtfile/where/you/have/keep/ /on/server/googlecaptcha.crt"
注意:我已將www.google.com.crt重命名為 googlecaptcha.crt,同時更改位置參數。
安裝證書后,您可以使用列表命令(在步驟 1 中給出)來驗證它。
這是完成上述過程后的代碼片段:
try {
URL url = new URL(googleURL);
if(proxy!=null){
conn = (HttpURLConnection)url.openConnection(proxy);
}else{
conn = (HttpURLConnection)url.openConnection();
}
conn.setRequestMethod("POST");
conn.setRequestProperty("Accept", "application/json");
InputStreamReader in = new InputStreamReader(conn.getInputStream());
BufferedReader br = new BufferedReader(in);
StringBuilder sb = new StringBuilder();
String output;
while ((output = br.readLine()) != null) {
System.out.println(output);
sb.append(output);
}
String responseNew = sb.toString();
responseObject = (ImplValidateCaptchaGoogleResponse)this.mapper.readValue(responseNew, ImplValidateCaptchaGoogleResponse.class);
} catch (Exception e) {
LOGGER.debug("ERROR_OCCURED ::"+e.getMessage() );
e.printStackTrace();
}
}
如果您處於開發模式且證書無效,為什么不設置weClient.setUseInsecureSSL(true)
。 為我工作
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.