解决unable to find valid certification path to requested target...的问题

本文介绍了解决在向服务器发送HTTP POST请求时遇到的HTTPS证书验证问题的方法。通过创建一个特殊的HttpClient实例,该实例忽略所有HTTPS证书验证,从而避免了SSLPeerUnverifiedException异常。

今天在向服务器发送http post请求的时候出现了unable to find valid certification path to requested target的错误,百度了下需要证书啥的。解决方式是在发送http请求的时候,可以过滤掉所有的https证书验证。
代码如下:

	/**
	 * POST请求
	 * 
	 * @param url
	 * @param data
	 * @return
	 */
	public String sendPost() {
		LOG.info("send to tanggong : " + data);
		String result = null;
		CloseableHttpClient httpClient = HttpClients.createDefault();
		//isNoSSL是否需要走特殊方法
		if(isNoSSL)  
		{  
			httpClient = (CloseableHttpClient)wrapClient(httpClient);  
		} 
		HttpPost post = new HttpPost(httpUrl);
		post.addHeader("Content-type","application/json; charset=utf-8");
		post.setHeader("Accept", "application/json");
		CloseableHttpResponse response = null;
		try {
			StringEntity sen = new StringEntity(data.toString(),Charset.forName("UTF-8"));
			sen.setContentEncoding("UTF-8");
			sen.setContentType("application/json");
			post.setEntity(sen);
			response = httpClient.execute(post);
			if (response != null && response.getStatusLine().getStatusCode() == 200) {
				HttpEntity entity = response.getEntity();
				result = EntityUtils.toString(entity);
			}
			LOG.info("ZP return :" + result);
			return result;
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				httpClient.close();
				if (response != null) {
					response.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	
	/** 
	 * 避免HttpClient的”SSLPeerUnverifiedException: peer not authenticated”异常 
	 * 不用导入SSL证书 
	 * @param base 
	 * @return 
	 */  
	public static HttpClient wrapClient(HttpClient base) {  
	    try {  
	        SSLContext ctx = SSLContext.getInstance("TLS");  
	        X509TrustManager tm = new X509TrustManager() {  
	       
				@Override
				public void checkClientTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
						throws java.security.cert.CertificateException {
					// TODO Auto-generated method stub
					
				}

				@Override
				public void checkServerTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
						throws java.security.cert.CertificateException {
					// TODO Auto-generated method stub
					
				}

				@Override
				public java.security.cert.X509Certificate[] getAcceptedIssuers() {
					// TODO Auto-generated method stub
					return null;
				}  
	        };  
	        ctx.init(null, new TrustManager[] { tm }, null);  
	        SSLConnectionSocketFactory ssf = new SSLConnectionSocketFactory(ctx,NoopHostnameVerifier.INSTANCE);  
	        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(ssf).build();  
	        return httpclient;  
	    } catch (Exception ex) {  
	        ex.printStackTrace();  
	        return HttpClients.createDefault();  
	    }  
	}  
### 解决方案概述 当遇到 `SunCertPathBuilderException: unable to find valid certification path to requested target` 错误时,这通常意味着Java应用程序无法验证服务器提供的SSL证书的有效性。解决方案涉及将所需的CA证书导入到Java的信任库中。 ### 方法一:手动添加证书至信任库 为了使程序能够识别并信任特定的SSL证书,可以将其添加到Java KeyStore文件中。具体操作如下: 1. 使用命令行工具获取完整的证书链,并保存为PEM格式文件。 2. 将该证书加入名为`jssecacerts`的新KeyStore文件内[^1]: ```bash keytool -importcert -file server_cert.pem -keystore jssecacerts -storepass changeit ``` 3. 配置JSSE以使用此新的trust store作为其信任源;或者直接把生成好的`jssecacerts`复制到JDK安装路径下对应的security目录里去覆盖原有的cacerts文件。 4. 如果希望所有基于当前环境运行的Java应用都能认可新增加的根证书,则可以直接替换掉$JAVA_HOME/jre/lib/security/cacerts文件的内容。 ### 方法二:编程方式绕过认证(不推荐用于生产) 对于某些特殊情况,在开发测试阶段可能并不关心严格的双向身份验证机制。此时可以通过自定义TrustManager类来实现对任意主机名和公钥的接受行为,从而达到跳过标准TLS握手过程中客户端对服务端的身份确认过程的目的[^2]。 注意这种方法存在安全隐患,仅适用于内部网络环境下快速搭建原型系统或调试目的,正式上线前务必移除此类代码逻辑! ```java // 创建一个默认的SSLSocketFactory实例 SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, new TrustManager[]{new X509TrustManager() { public void checkClientTrusted(X509Certificate[] chain, String authType) {} public void checkServerTrusted(X509Certificate[] chain, String authType) {} public X509Certificate[] getAcceptedIssuers() {return null;} }}, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); ``` ### 方法三:更新本地机器上的受信CAs列表 有时问题并非在于远程站点本身,而是因为本地计算机缺少必要的中间件或根级颁发机构信息而导致整个链条断裂。因此定期同步最新的官方发布版本也是解决问题的一种有效手段之一[^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值