1.在httpclient发起请求时,有时会出现下面这种情况
你的日志中出现有关SSL的异常,javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated,我们会注意到SSL这几个字母,这是和https提交时有关的地方。
2.什么是SSL证书
SSL证书,也称为服务器SSL证书,是遵守SSL协议的一种数字证书,由全球信任的证书颁发机构(CA)验证服务器身份后颁发。将SSL证书安装在网站服务器上,可实现网站身份验证和数据加密传输双重功能,有效防止机密数据在传输过程中被窃取和纂改,有效防止钓鱼网站浑水摸鱼盗取用户财产。
3.解决方法--忽略SSL证书
3.1忽略SSL证书的流程
- 简介:需要告诉client使用一个不同的TrustManager。TrustManager是一个检查给定的证书是否有效的类。SSL使用的模式是X.509,对于该模式Java有一个特定的TrustManager,称为X509TrustManager。首先我们需要创建这样的TrustManager。将TrustManager设置到我们的HttpClient。TrustManager只是被SSL的Socket所使用。Socket通过SocketFactory创建。对于SSL Socket,有一个SSLSocketFactory。当创建新的SSLSocketFactory时,你需要传入SSLContext到它的构造方法中。在SSLContext中,我们将包含我们新创建的TrustManager。
- 创建的TrustManager
- 创建SSLContext:TLS是SSL的继承者,但是它们使用相同的SSLContext。
- 创建SSLSocketFactory
- 将SSLSocketFactory注册到我们的HttpClient上。这是在SchemeRegistry中完成的。
- 创建ClientConnectionManager,创建SchemeRegistry。
- 生成HttpClient
3.2代码实现
1 import java.security.cert.CertificateException; 2 import java.security.cert.X509Certificate; 3 4 import javax.net.ssl.SSLContext; 5 import javax.net.ssl.TrustManager; 6 import javax.net.ssl.X509TrustManager; 7 8 import org.apache.http.client.HttpClient; 9 import org.apache.http.conn.ClientConnectionManager; 10 import org.apache.http.conn.scheme.Scheme; 11 import org.apache.http.conn.scheme.SchemeRegistry; 12 import org.apache.http.conn.ssl.SSLSocketFactory; 13 import org.apache.http.impl.client.DefaultHttpClient; 14 15 public class WebClientDevWrapper { 16 17 public static HttpClient wrapClient(HttpClient base) { 18 try { 19 SSLContext ctx = SSLContext.getInstance("TLS"); 20 X509TrustManager tm = new X509TrustManager() { 21 public X509Certificate[] getAcceptedIssuers() { 22 return null; 23 } 24 public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {} 25 public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {} 26 }; 27 ctx.init(null, new TrustManager[] { tm }, null); 28 SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 29 30 ClientConnectionManager ccm=base.getConnectionManager(); 31 SchemeRegistry registry = ccm.getSchemeRegistry(); 32 registry.register(new Scheme("https", 443, ssf)); 33 return new DefaultHttpClient(ccm, base.getParams()); 34 35 /* SchemeRegistry registry = new SchemeRegistry(); 36 registry.register(new Scheme("https", 443, ssf)); 37 ThreadSafeClientConnManager mgr = new ThreadSafeClientConnManager(registry); 38 return new DefaultHttpClient(mgr, base.getParams());*/ 39 } catch (Exception ex) { 40 ex.printStackTrace(); 41 return null; 42 } 43 } 44 }
对应的httpclient提交为:
HttpClient httpClient = WebClientDevWrapper.wrapClient(new DefaultHttpClient()); HttpPost post = new HttpPost(url);
注:这里有一点要说明,有的时候即使加入这段代码也还是会抛异常,个人在查找资料的时候发现,javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated,这种异常还与jdk版本有关,在上边代码的第19行(TLS),这里可以换上与你jdk环境相对应的通信协议TLSv:
- jdk6默认对应的是TLSv1;但还可以是TLSv1.1和SSLv3。
- jdk7默认对应的是TLSv1;但还可以是TLSv1.1、TLSv1.2和SSLv3。
- jdk3默认对应的是TLSv1.2;但还可以是TLSv、TLSv1.1和SSLv3。
所以要根据自身的实际情况更改对应的通信协议。