使用HttpClient时,尝试通过HTTPS进行通信时收到以下错误:
线程"main"中的异常javax.net.ssl.SSLPeerUnverifiedException:peer未经过身份验证.
这是我的代码:
URI loginUri = new URI("https://myUrl.asp"); HttpClient httpclient = new DefaultHttpClient(); HttpGet httpget = new HttpGet( loginUri ); HttpResponse response = httpclient.execute( httpget );
如何抑制或删除此错误?
注意:请勿在生产代码中执行此操作,而是使用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; } }
这个答案是关于owlstead和Mat的回答.它适用于SE/EE安装,而不适用于ME /移动/ Android SSL.
由于还没有人提到它,我将提到修复此问题的"生产方式":按照HttpClient中的AuthSSLProtocolSocketFactory类中的步骤更新您的信任库和密钥库.
导入受信任的证书并生成信任库文件
keytool -import -alias "my server cert" -file server.crt -keystore my.truststore
生成新密钥(使用与信任库相同的密码)
keytool -genkey -v -alias "my client key" -validity 365 -keystore my.keystore
发出证书签名请求(CSR)
keytool -certreq -alias "my client key" -file mycertreq.csr -keystore my.keystore
(自签或签署证书)
导入受信任的CA根证书
keytool -import -alias "my trusted ca" -file caroot.crt -keystore my.keystore
导入包含完整证书链的PKCS#7文件
keytool -import -alias "my client key" -file mycert.p7 -keystore my.keystore
验证生成的密钥库文件的内容
keytool -list -v -keystore my.keystore
如果您没有服务器证书,请以JKS格式生成一个,然后将其导出为CRT文件.来源:keytool文档
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
使用HttpClient 3.x,您需要这样做:
Protocol easyHttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443); Protocol.registerProtocol("https", easyHttps);
可以在此处找到EasySSLProtocolSocketFactory的实现.