赞
踩
这个方法的代码如下:
- public static String httpsPostInvoke(String url,Map<String, Object> map) throws IOException, ServiceException {
-
- HttpClient client = new DefaultHttpClient();
- String str = "";
-
- try {
- X509TrustManager xtm = new X509TrustManager(){ //创建TrustManager
- public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
- public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
- public X509Certificate[] getAcceptedIssuers() { return null; }
- };
- SSLContext ctx = SSLContext.getInstance("TLS");
- ctx.init(null, new TrustManager[]{xtm}, null);
- SSLSocketFactory socketFactory = new SSLSocketFactory(ctx,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
- client.getConnectionManager().getSchemeRegistry().register(new Scheme("https", 443, socketFactory));
-
- List<NameValuePair> params = new ArrayList<NameValuePair>();//构建POST请求的参数
- for (String key : map.keySet()) {
- String value = null;
- Object obj = null;
- if((obj = map.get(key)) != null){
- value = obj.toString();
- }
- params.add(new BasicNameValuePair(key, value));
- }
- UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, "UTF-8");
- HttpPost post = new HttpPost(url);//创建HttpPost
- post.setEntity(entity);
-
-
- HttpResponse response = client.execute(post);
- if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
- throw new ServiceException("Http接口状态出错("
- + response.getStatusLine().getStatusCode() + ")");
- }
- str = EntityUtils.toString(response.getEntity());
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- } catch (KeyManagementException e) {
- e.printStackTrace();
- } catch (Exception e) {
- e.printStackTrace();
- }finally {
- client.getConnectionManager().shutdown();
- return str;
- }
- }
执行,ok,没报javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
但是,信任所有的证书,对于强迫症的我和程序猿绝对不能写死的一贯原则,我...又TM花了很长时间,脑补了很多ssl、https的知识,结合网上的代码,发现是可以信任指定证书的,如下代码:
- public static String httpsPostInvoke(String url,Map<String, Object> map) throws IOException, ServiceException {
-
- InputStream inputStream = null;
- HttpClient httpClient = new DefaultHttpClient();
- String result = "";
-
- try{
- //从 inputStream 加载 CA 证书
- inputStream = NetworkUtil.class.getResourceAsStream("/testCa.cer");
- CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
- Certificate certificate = certificateFactory.generateCertificate(inputStream);
-
- //构造含有信任 CA 证书的 KeyStore
- KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
- trustStore.load(null, null);
- trustStore.setCertificateEntry("myalias", certificate);
-
- SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
- httpClient.getConnectionManager().getSchemeRegistry().register(new Scheme("https", 443, socketFactory));
-
- List<NameValuePair> params = new ArrayList<NameValuePair>();//构建POST请求的参数
- for (String key : map.keySet()) {
- String value = null;
- Object obj = null;
- if((obj = map.get(key)) != null){
- value = obj.toString();
- }
- params.add(new BasicNameValuePair(key, value));
- }
- UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, "UTF-8");
- HttpPost post = new HttpPost(url);
- post.setEntity(entity);
-
- HttpResponse response = httpClient.execute(post);
- if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
- throw new ServiceException("Http接口状态出错("
- + response.getStatusLine().getStatusCode() + ")");
- }
- result = EntityUtils.toString(response.getEntity());
- } catch (CertificateException e) {
- e.printStackTrace();
- } catch (KeyStoreException e) {
- e.printStackTrace();
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- } catch (KeyManagementException e) {
- e.printStackTrace();
- } catch (UnrecoverableKeyException e) {
- e.printStackTrace();
- } finally {
-
- if(null != inputStream){
- inputStream.close();
- }
-
- httpClient.getConnectionManager().shutdown();
- }
-
- return result;
-
- }
执行......还是javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
要把证书导入到jdk的KeyStore中,如下命令(相信聪明的你看路径和文件名知道怎么修改相应的参数了吧):
keytool -importcert -alias myalias -file "C:\Users\zhangxiaoning\Desktop\testCa.cer" -keystore "D:\Java\jdk1.6.0_45\jre\lib\security\cacerts" -storepass changeit
另外,骚年们想看命令的说明可以参考一下blog,传送门:
其他默认就行了。
运行程序...
javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
我也不知道怎么表述我的心情了。
找资料,看到了一个blog说好像是jdk版本问题,把jdk1.6.0_45\jre\lib\security下的两个jar包换成jdk1.6以上的jar包,换了后执行直接报了classnotfound
算了,先用jdk1.7的执行,调用成功 = =
但是公司的很多系统都是用jdk1.6的,用jdk1.7的话,可能会有问题,所以继续找资料。
在无意中,百度到了一句,java ssl网络的debug log打印,在你要调用接口前加入以下一句:
System.setProperty("javax.net.debug", "ssl,handshake");
调用https接口前会打印一系列log,前面一堆的可以忽略,直接看最下面的,比如我的:
知道了问题,搜索的范围变小了很多了,直接百度:javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate DH keypair
查看了很多资料,终于找到了原因,jdk1.6只支持1024字节的DH,我发现我证书的公钥是2048字节的,所以报错了,jdk1.7以上支持,所以成功。
可以查看详细的说明:
传送门:https://stackoverflow.com/questions/6851461/java-why-does-ssl-handshake-give-could-not-generate-dh-keypair-exception
https://github.com/syncany/syncany/issues/483
所以解决方法是:
1.下载jar包:传送门:http://download.csdn.net/detail/nk_tf/9609842 (先前在csdn上下载了一份,发现是坏的jar包,我的1分没了,气死我了~~)
2.复制这两个jar包到: $JAVA_HOME/jre/lib/ext
3.编辑$JAVA_HOME/jre/lib/security/java.security,在9下面加入这句:
security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider
security.provider.1=sun.security.provider.Sun
security.provider.2=sun.security.rsa.SunRsaSign
security.provider.3=com.sun.net.ssl.internal.ssl.Provider
security.provider.4=com.sun.crypto.provider.SunJCE
security.provider.5=sun.security.jgss.SunProvider
security.provider.6=com.sun.security.sasl.Provider
security.provider.7=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.8=sun.security.smartcardio.SunPCSC
security.provider.9=sun.security.mscapi.SunMSCAPI
security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider
重新调用,没报错,OK!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。