java访问https请求

来源:互联网 发布:淘宝第五大道是正品吗 编辑:程序博客网 时间:2024/05/17 23:28

转载自


http://rutine.blog.163.com/blog/static/790808722013115105143588/



使用HttpClient 4.0访问https时遇到一个烦心的问题,网上查找的资料都没能解决我所遇到的问题。在此记录一下后来怎样解决的,这里有两点需要注意:
1. 包装HttpClient对象,以达到忽略证书验证的目的
2. 导入需要的jar包

// 这是在eclipse下打印出来的stackoverflow信息:

javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
at com.sun.net.ssl.internal.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:352)
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:126)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:437)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:643)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:479)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784)
at com.kangli.api.spsr.PreAlertService.login(PreAlertService.java:68)
at com.kangli.api.spsr.PreAlertService.main(PreAlertService.java:52


上面的异常信息主要意思是:证书验证不通过。就是说你所访问网站的证书不在你可以信任的证书列表中,下面是我的代码...
// 这个我的代码,修改过...
//HttpClient httpClient = getSecuredHttpClient(new DefaultHttpClient()); // 处理https协议 1
HttpClient httpClient = new DefaultHttpClient(); // 创建HttpClient 2
HttpPost httpPost = new HttpPost("https://xxx.com"); // 这里是你要访问的https域名
httpPost.addHeader("Content-Type", "application/xml; charset=utf-8");
httpPost.addHeader("User-Agent", "Mozilla/5.0");
MultipartEntity multipartEntity = new MultipartEntity();
multipartEntity.addPart("data", new FileBody(new File("yourfilename.xml")));
httpPost.setEntity(multipartEntity);
try {
HttpResponse httpResponse = httpClient.execute(httpPost);
int statusCode = httpResponse.getStatusLine().getStatusCode();
if(statusCode == HttpStatus.SC_OK){
System.out.println("服务器正常响应.....");
HttpEntity resEntity = httpResponse.getEntity();
System.out.println(EntityUtils.toString(resEntity));//httpclient自带的工具类读取返回数据
System.out.println(resEntity.getContent());
EntityUtils.consume(resEntity);
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
可以这样做,重新包装httpclient对象,忽略证书验证,代码如下:

private static DefaultHttpClient getSecuredHttpClient(HttpClient httpClient) {
final X509Certificate[] _AcceptedIssuers = new X509Certificate[] {};
try {
SSLContext ctx = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return _AcceptedIssuers;
}

@Override
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}

@Override
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
};
ctx.init(null, new TrustManager[] { tm }, new SecureRandom());
SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
ClientConnectionManager ccm = httpClient.getConnectionManager();
SchemeRegistry sr = ccm.getSchemeRegistry();
sr.register(new Scheme("https", 443, ssf));
return new DefaultHttpClient(ccm, httpClient.getParams());
} catch (Exception e) {
System.out.println("=====:=====");
e.printStackTrace();
}
return null;
}

除掉代码1注释,注释掉代码2,运行一下。这时如果java环境配置正确的话就不会出现异常。否则还是会出现 javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated异常,原因是classpath 没有导入需要的jar包:
HttpCLient 访问https协议出现: javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated - rutine - rutine
      主要是sunjce_provider.jar 这个包。我一开始是在JAVA_HOME/jre环境下运行,就算包装过的httpclient对象还是报上面那个异常,后来改为JAVA_HOME/jdk1.6.0_33/jre,eclipse就会出现上面红圈的jar包,程序可以正常跑了。
      或者导入你所访问网站的安全证书在你的java运行环境里,在程序new DefaultHttpClient()访问https就不会抛这个异常。