HttpClient的”javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated”异常

你猜 阅读:591 2021-03-31 22:46:26 评论:0

在开发https应用时,你的测试服务器常常没有一个(有效的)SSL证书。在你的客户端连接测试服务器时,如下的异常会被抛出:”javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated”。

我将讨论使用Apache HttpClient时,解决该问题的一种方法(http://hc.apache.org/httpcomponents-client/)。

 

1. 代码片段

通常,你会像下面那样来创建HttpClient:

我们将需要告诉client使用一个不同的TrustManager。TrustManager(http://download.oracle.com/docs/cd/E17476_01/javase/1.5.0/docs/api/javax/net/ssl/TrustManager.html)是一个检查给定的证书是否有效的类。SSL使用的模式是X.509(http://en.wikipedia.org/wiki/X.509),对于该模式Java有一个特定的TrustManager,称为X509TrustManager。首先我们需要创建这样的TrustManager。

下面我们需要找到一个将TrustManager设置到我们的HttpClient的方法。TrustManager只是被SSL的Socket所使用。Socket通过SocketFactory创建。对于SSL Socket,有一个SSLSocketFactory(http://download.oracle.com/docs/cd/E17476_01/javase/1.5.0/docs/api/javax/net/ssl/SSLSocketFactory.html)。当创建新的SSLSocketFactory时,你需要传入SSLContext到它的构造方法中。在SSLContext中,我们将包含我们新创建的TrustManager。

首先我们需要得到一个SSLContext:

TLS是SSL的继承者,但是它们使用相同的SSLContext。

然后我们需要使用我们上面新创建的TrustManager来初始化该上下文:

最后我们创建SSLSocketFactory:

现在我们仍然需要将SSLSocketFactory注册到我们的HttpClient上。这是在SchemeRegistry中完成的:

我们注册了一个新的Scheme,使用协议https,我们新创建的SSLSocketFactory包含了我们的TrustManager,然后我们告诉HttpClienthttps的默认端口是443.


2. 完整示例代码

下面的类接收HttpClient作为参数,然后返回一个新的接受任意SSL证书的HttpClient:

package com.vixuan.vplex; 
 
import java.io.IOException; 
import java.io.UnsupportedEncodingException; 
import java.security.cert.CertificateException; 
import java.security.cert.X509Certificate; 
import java.util.ArrayList; 
import java.util.List; 
 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.TrustManager; 
import javax.net.ssl.X509TrustManager; 
 
import org.apache.http.HttpEntity; 
import org.apache.http.HttpResponse; 
import org.apache.http.NameValuePair; 
import org.apache.http.ParseException; 
import org.apache.http.client.ClientProtocolException; 
import org.apache.http.client.HttpClient; 
import org.apache.http.client.entity.UrlEncodedFormEntity; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.conn.ClientConnectionManager; 
import org.apache.http.conn.scheme.Scheme; 
import org.apache.http.conn.scheme.SchemeRegistry; 
import org.apache.http.conn.ssl.SSLSocketFactory; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.apache.http.message.BasicNameValuePair; 
import org.apache.http.util.EntityUtils; 
 
 
 
 
 
 
public class PostDemo { 
 
	/** 
	 * @param args 
	 */ 
	public static void main(String[] args) { 
		// TODO Auto-generated method stub 
		//请求格式https://mgmt-server-ip/vplex/clusters/cluster-name 
		String url="https://172.16.1.5/vplex/clusters/cluster-1"; 
		 
		List<NameValuePair> params=new ArrayList<NameValuePair>(); 
		params.add(new BasicNameValuePair("Username","Service")); 
		params.add(new BasicNameValuePair("Password","Mi@Dim77")); 
		params.add(new BasicNameValuePair("args","cluster status")); 
		 
		String result=sendPost(url,params); 
		System.out.println(result); 
		 
		 
	} 
	 
	 
	 
	public static String sendPost(String url,List<NameValuePair> params){ 
		String result=""; 
		 
		 HttpClient client1 = new DefaultHttpClient(); 
		 HttpClient client =WebClientDevWrapper.wrapClient(client1); 
         HttpPost httppost = new HttpPost(url);  
          
         try {   
             // Post请求   
             // 设置参数   
             httppost.setEntity(new UrlEncodedFormEntity(params,"UTF-8"));   
             // 发送请求   
             HttpResponse httpresponse = client.execute(httppost);   
             HttpEntity entity = httpresponse.getEntity();   
             result = EntityUtils.toString(entity);   
             System.out.println(result);   
         } catch (UnsupportedEncodingException e) {   
             // TODO Auto-generated catch block   
             e.printStackTrace();   
         } catch (ClientProtocolException e) {   
             // TODO Auto-generated catch block   
             e.printStackTrace();   
         } catch (ParseException e) {   
             // TODO Auto-generated catch block   
             e.printStackTrace();   
         } catch (IOException e) {   
             // TODO Auto-generated catch block   
             e.printStackTrace();   
         }   
		  
		return result; 
	} 
	<span style="color:#ff0000;"> public static class WebClientDevWrapper { 
	 
	public static HttpClient wrapClient(HttpClient base)  
	{ 
	    try { 
	        SSLContext ctx = SSLContext.getInstance("TLS"); 
	        X509TrustManager tm = new X509TrustManager() { 
 
	            public void checkClientTrusted(X509Certificate[] chain, 
	                    String authType) throws CertificateException 
	            { 
	                // TODO Auto-generated method stub 
 
	            } 
 
	            public void checkServerTrusted(X509Certificate[] chain, 
	                    String authType) throws CertificateException 
	            { 
	                // TODO Auto-generated method stub 
 
	            } 
 
	            public X509Certificate[] getAcceptedIssuers() 
	            { 
	                // TODO Auto-generated method stub 
	                return null; 
	            } 
 
	        }; 
	        ctx.init(null, new TrustManager[] { tm }, null); 
	        SSLSocketFactory ssf = new SSLSocketFactory(ctx); 
	        ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 
	        ClientConnectionManager ccm = base.getConnectionManager(); 
	        SchemeRegistry sr = ccm.getSchemeRegistry(); 
	        //设置要使用的端口,默认是443 
	        sr.register(new Scheme("https", ssf, 443)); 
	        return new DefaultHttpClient(ccm, base.getParams()); 
	    } catch (Exception ex) { 
	        ex.printStackTrace(); 
	        return null; 
	    } 
	}</span> 
	 
} 
	 
	 
	 
	 
	 
	 
	 
 
} 


声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

搜索
关注我们

一个IT知识分享的公众号