Https SSL加密Rest Cilent访问,证书不通过的问题

近期要写一个Rest Client访问HTTPS协议的URL,用Post方式以JSON格式拿回URL的数据。最开始选择的Client是javax.ws.rs-2.0.jar这个jar包,Client的创建方式是:

Client client = ClientBuilder.newClient();

遇到的第一个问题就是证书不通过,具体如下:

SEVERE: Error while committing the request output stream.
javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present

网上折腾了半天,想到换一种Client的创建方式,如下:

Client client = ClientBuilder.newBuilder().hostnameVerifier(new HostnameVerifier() {
			@Override
			public boolean verify(String hostname, SSLSession session) {
				// TODO Auto-generated method stub
				return true;
			}
	}).build();
这样之后,出现一个新的问题,如下:

SEVERE: Error while committing the request output stream.
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
这个问题,网上看了很久,有的说缺少指定hostname的SSL证书,用代码生成一个,(http://blog.csdn.net/faye0412/article/details/6883879)并把这个证书放到$JAVA_HOME$/jre/lib/security/文件夹下,我倒腾了一会也没能正常生成这个证书,于是放弃这个方法。

最后,想到是不是Client不对,于是换成HttpClient,没想到结果是一样的。最后终于找到了解决办法,共享一下:

使用Jersey REST客户端调用REST Web服务,主要包括三个jar包:jersey-client-1.18.jar,jersey-core-1.18.jar和jersy-json-q.q8.jar来生成Client,来实现带不可信SSL证书的Rest API服务,具体实现如下:

package restsample;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.ws.rs.core.MediaType;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.client.urlconnection.HTTPSProperties;

public class RestSnow {
	public static ClientConfig init() throws NoSuchAlgorithmException, KeyManagementException {
			SSLContext context = SSLContext.getInstance("SSL");
			TrustManager[] trustAllCerts = new TrustManager[] { 
					new X509TrustManager() {
					    public X509Certificate[] getAcceptedIssuers() {
					        return null;
					    }
					    @Override
					    public void checkClientTrusted(X509Certificate[] certs, String authType) {}
					    @Override
					    public void checkServerTrusted(X509Certificate[] certs, String authType) {}
					}
			};
		
			context.init(null, trustAllCerts, new SecureRandom());
			HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
			
			ClientConfig config = new DefaultClientConfig();
			config.getProperties().put(
				HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,
				new HTTPSProperties(new HostnameVerifier() {
					public boolean verify(String s, SSLSession sslSession) {
						return true;
					}
				}, context)
			);
		return config;
	}


	public static void main(String[] args) {
		try {
			ClientConfig config = init();
			Client client = Client.create(config);
			client.setFollowRedirects(true);
			WebResource resource = client.resource("https://65.50.203.159/api/data?auth_token=XzRso6mnz5FoKy2bYhNY");
			resource.accept(MediaType.APPLICATION_JSON_TYPE);

			String postContent = "{\"dataSource\": \"rb_flow\",\"granularity\":{\"type\": \"period\",\"period\": \"pt5m\",\"timeZone\": \"America/Los_Angeles\",\"origin\": \"2014-04-05T12:00:00.000+08:00\"},\"intervals\":[\"2014-04-05T13:01:00+08:00/2014-04-06T13:01:00+08:00\"],\"queryType\": \"timeseries\",\"aggregations\":[{\"type\": \"dimCardinality\",\"name\": \"result\",\"fieldName\": \"ap_mac\"}]}";
			// Post 方式
			ClientResponse response = resource.type(MediaType.APPLICATION_JSON_TYPE).
					post(ClientResponse.class, con);
			
			// 将返回结果写入到本地文件中
//			System.out.println("Output : \n" + response.getEntity(String.class));
//			System.out.println(response.toString());
//			System.out.println(response.getEntityInputStream());
			InputStream inputStream = response.getEntityInputStream();
			String fileName = "result.txt";
			File f = new File("C:/"+fileName);
			
			FileOutputStream fos = new FileOutputStream(f);
			System.out.println("复制文件:" + inputStream.available() + "字节");
			
			byte[] buffer = new byte[1024];
			while(true) {
				if(inputStream.available() < 1024) {
					int c = -1;
					while((c = inputStream.read()) != -1) {
						fos.write(c);
					}
					break;
				}
				else {
					// 从来源文件读取数据至缓冲区
					inputStream.read(buffer);
					 // 将数组数据写入目的文件
					fos.write(buffer);
				}
			}
			inputStream.close();
			fos.close();
			
			
		} catch(NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (KeyManagementException e) {
			e.printStackTrace();
		}  catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
在此供参考,以后遇到相同的问题再回顾。


你可能感兴趣的:(网页学习,ssl,Rest,Client,web服务,security,REST)