Java HTTPS:SSLPeerUnverifiedException的HttpGet
使用,我在尝试通过HTTPS进行通信时收到以下错误: 线程“main”javax.net.ssl.SSLPeerUnverifiedException中的异常:对等未经身份验证 这是我的密码:Java HTTPS:SSLPeerUnverifiedException的HttpGet,java,ssl,https,httpclient,Java,Ssl,Https,Httpclient,使用,我在尝试通过HTTPS进行通信时收到以下错误: 线程“main”javax.net.ssl.SSLPeerUnverifiedException中的异常:对等未经身份验证 这是我的密码: URI loginUri = new URI("https://myUrl.asp"); HttpClient httpclient = new DefaultHttpClient(); HttpGet httpget = new HttpGet( loginUri ); HttpResponse re
URI loginUri = new URI("https://myUrl.asp");
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet( loginUri );
HttpResponse response = httpclient.execute( httpget );
如何抑制或删除此错误?使用HttpClient 3.x,您需要执行以下操作:
Protocol easyHttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
Protocol.registerProtocol("https", easyHttps);
可以找到EasySSLProtocolSocketFactory的实现。注意:不要在生产代码中执行此操作,而是使用http,或者使用上面建议的实际自签名公钥 在HttpClient 4.xx上:
import static org.junit.Assert.assertEquals;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.junit.Test;
public class HttpClientTrustingAllCertsTest {
@Test
public void shouldAcceptUnsafeCerts() throws Exception {
DefaultHttpClient httpclient = httpClientTrustingAllSSLCerts();
HttpGet httpGet = new HttpGet("https://host_with_self_signed_cert");
HttpResponse response = httpclient.execute( httpGet );
assertEquals("HTTP/1.1 200 OK", response.getStatusLine().toString());
}
private DefaultHttpClient httpClientTrustingAllSSLCerts() throws NoSuchAlgorithmException, KeyManagementException {
DefaultHttpClient httpclient = new DefaultHttpClient();
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, getTrustingManager(), new java.security.SecureRandom());
SSLSocketFactory socketFactory = new SSLSocketFactory(sc);
Scheme sch = new Scheme("https", 443, socketFactory);
httpclient.getConnectionManager().getSchemeRegistry().register(sch);
return httpclient;
}
private TrustManager[] getTrustingManager() {
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {
// Do nothing
}
@Override
public void checkServerTrusted(X509Certificate[] certs, String authType) {
// Do nothing
}
} };
return trustAllCerts;
}
}
方法返回“secureClient”(在Java 7环境中-NetBeans IDE和GlassFish服务器:端口https默认为3920),希望这能有所帮助:
public DefaultHttpClient secureClient() {
DefaultHttpClient httpclient = new DefaultHttpClient();
SSLSocketFactory sf;
KeyStore trustStore;
FileInputStream trustStream = null;
File truststoreFile;
// java.security.cert.PKIXParameters for the trustStore
PKIXParameters pkixParamsTrust;
KeyStore keyStore;
FileInputStream keyStream = null;
File keystoreFile;
// java.security.cert.PKIXParameters for the keyStore
PKIXParameters pkixParamsKey;
try {
trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
truststoreFile = new File(TRUSTSTORE_FILE);
keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keystoreFile = new File(KEYSTORE_FILE);
try {
trustStream = new FileInputStream(truststoreFile);
keyStream = new FileInputStream(keystoreFile);
} catch (FileNotFoundException ex) {
Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
}
try {
trustStore.load(trustStream, PASSWORD.toCharArray());
keyStore.load(keyStream, PASSWORD.toCharArray());
} catch (IOException ex) {
Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
} catch (CertificateException ex) {
Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
}
try {
pkixParamsTrust = new PKIXParameters(trustStore);
// accepts Server certificate generated with keytool and (auto) signed by SUN
pkixParamsTrust.setPolicyQualifiersRejected(false);
} catch (InvalidAlgorithmParameterException ex) {
Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
}
try {
pkixParamsKey = new PKIXParameters(keyStore);
// accepts Client certificate generated with keytool and (auto) signed by SUN
pkixParamsKey.setPolicyQualifiersRejected(false);
} catch (InvalidAlgorithmParameterException ex) {
Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
}
try {
sf = new SSLSocketFactory(trustStore);
ClientConnectionManager manager = httpclient.getConnectionManager();
manager.getSchemeRegistry().register(new Scheme("https", 3920, sf));
} catch (KeyManagementException ex) {
Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
} catch (UnrecoverableKeyException ex) {
Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
} catch (KeyStoreException ex) {
Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
}
// use the httpclient for any httpRequest
return httpclient;
}
这个答案是根据和的回答得出的。它适用于SE/EE安装,而不是ME/mobile/Android SSL
由于还没有人提到这一点,我将提到解决这一问题的“生产方式”:
按照中的步骤更新您的信任存储和密钥存储
keytool-import-别名“我的服务器证书”-file server.crt-keystore my.truststore
keytool-genkey-v-别名“我的客户端密钥”-有效期365-密钥库我的密钥库
keytool-certreq-别名“我的客户端密钥”-文件mycertreq.csr-keystore my.keystore
keytool-import-alias“my trusted ca”-文件caroot.crt-keystore my.keystore
keytool-import-别名“我的客户端密钥”-文件mycert.p7-密钥库my.keystore
keytool-list-v-keystoremy.keystore
如果您没有服务器证书,请生成一个JKS格式的证书,然后将其导出为CRT文件
如果您的服务器基于JDK 7,而您的客户端位于JDK 6上并使用SSL证书,则会出现此异常。在JDK 7中,默认情况下禁用sslv2hello消息握手,而在JDK 6中启用sslv2hello消息握手。因此,当您的客户端尝试连接服务器时,将向服务器发送sslv2hello消息,并且由于sslv2hello消息禁用,您将获得此异常。要解决这个问题,您必须将客户端移动到JDK 7,或者必须使用JDK的6u91版本。但是要获得这个版本的JDK,您必须获得本地JVM或远程服务器可能没有所需的密码。到这里来 并下载包含以下内容的zip文件: 美国出口政策.jar 及 local_policy.jar 替换现有文件(您需要在JVM中找到现有路径) 在Mac电脑上,我的路径就在这里。 /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/security
这对我很有用。JDK版本?HttpClient版本?此外,如果您可以提供完整的堆栈跟踪和URL(它是否是公共网站,您是否使用自签名证书),它可能会有所帮助。它是自签名证书。我链接到我使用的HttpClient版本(4.x,任何稳定的版本),我使用的是Java 6。无论连接到哪个站点,我都需要忽略此错误并执行get。读者可能对此相关问题感兴趣:请注意,最好创建一个特定的
密钥库
或信任管理器
,以连接到未经预安装的根证书之一验证的特定服务器,或者创建并使用自签名证书。如果您只是跳过了这个问题,那么您的SSL连接就不再安全了。更新了URL。你真正需要做的就是谷歌EasySSLProtocolSocketFactory
。确切的字符串非常具体,似乎没有坏的结果。应该注意的是,此方法完全符合问题的要求:它抑制错误消息。因为连接不安全,所以它实际上并不能解决问题。正确的方法是在您的信任存储中明确导入远程证书。这并不能解决问题,链接会指向一个已停止的页面:。而且,对于任何对安全感兴趣的人来说,这也不能解决根本问题。在您的证书存储中导入证书,但不要信任所有连接,因为您最好不要使用SSL。当然。在生产代码中执行上述操作会产生难以置信的反效果。但是,如果您不关心安全性,例如在针对开发服务器的端到端测试中,不依赖服务器证书是很好的。感谢您的编辑,明确显示此类安全警告不会有什么坏处。@owlstead“您最好不要使用SSL”我使用SSL只是为了加密,而不是为了向客户端验证服务器,这怎么不安全?我想你使用加密的目的是防止中间人读取你的数据。如果是这样的话,在不验证证书的情况下,您不知道谁在另一端,可能是中间的人代理通信,即解密、读取、加密、传递。您永远不会知道……值得注意的是,只有在您也需要实现客户端身份验证时(即,让服务器对客户端进行身份验证),才需要执行步骤2-7。在大多数情况下,仅步骤1就足够了。如何创建server.crt?编辑以包括server.crt创建步骤。
keytool -genkey -alias server-alias -keyalg RSA -keypass changeit
-storepass changeit -keystore my.keystore
keytool -export -alias server-alias -storepass changeit
-file server.crt -keystore my.keystore