赞
踩
本地jdk环境为1.7,访问HTTPS正常,部署到生产环境报Connect Rest错误,多方检查原来正式环境为jdk6,去访问别人的https时报错,下面是通过百度整理的解决方案;
首先要自己重写SSLSocketFactory这个类,
下面是自己重写的这个
- package com.mln.frame;
-
- import java.io.ByteArrayInputStream;
- import java.io.ByteArrayOutputStream;
- import java.io.DataOutputStream;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.net.InetAddress;
- import java.net.InetSocketAddress;
- import java.net.Socket;
- import java.net.UnknownHostException;
- import java.security.KeyStore;
- import java.security.Principal;
- import java.security.SecureRandom;
- import java.security.Security;
- import java.security.cert.CertificateExpiredException;
- import java.security.cert.CertificateFactory;
- import java.util.Hashtable;
- import java.util.LinkedList;
- import java.util.List;
-
- import javax.net.ssl.HandshakeCompletedListener;
- import javax.net.ssl.SSLPeerUnverifiedException;
- import javax.net.ssl.SSLSession;
- import javax.net.ssl.SSLSessionContext;
- import javax.net.ssl.SSLSocket;
- import javax.net.ssl.SSLSocketFactory;
- import javax.security.cert.X509Certificate;
-
- import org.bouncycastle.crypto.tls.Certificate;
- import org.bouncycastle.crypto.tls.CertificateRequest;
- import org.bouncycastle.crypto.tls.DefaultTlsClient;
- import org.bouncycastle.crypto.tls.ExtensionType;
- import org.bouncycastle.crypto.tls.TlsAuthentication;
- import org.bouncycastle.crypto.tls.TlsClientProtocol;
- import org.bouncycastle.crypto.tls.TlsCredentials;
- import org.bouncycastle.jce.provider.BouncyCastleProvider;
-
- /**
- * 建立一个自己的ssl类
- */
- public class TLSSocketConnectionFactory extends SSLSocketFactory{
-
- static {
- if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
- Security.addProvider(new BouncyCastleProvider());
- }
- }
-
- @Override
- public Socket createSocket(Socket socket, final String host, int port,
- boolean arg3) throws IOException {
- if (socket == null) {
- socket = new Socket();
- }
- if (!socket.isConnected()) {
- socket.connect(new InetSocketAddress(host, port));
- }
-
- final TlsClientProtocol tlsClientProtocol = new TlsClientProtocol(socket.getInputStream(), socket.getOutputStream(), new SecureRandom());
-
- return _createSSLSocket(host, tlsClientProtocol);
- }
-
- @Override public String[] getDefaultCipherSuites() { return null; }
- @Override public String[] getSupportedCipherSuites() { return null; }
- @Override public Socket createSocket(String host, int port) throws IOException, UnknownHostException { return null; }
- @Override public Socket createSocket(InetAddress host, int port) throws IOException { return null; }
- @Override public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { return null; }
- @Override public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { return null; }
-
- private SSLSocket _createSSLSocket(final String host, final TlsClientProtocol tlsClientProtocol) {
- return new SSLSocket() {
- private java.security.cert.Certificate[] peertCerts;
-
- @Override public InputStream getInputStream() throws IOException { return tlsClientProtocol.getInputStream(); }
- @Override public OutputStream getOutputStream() throws IOException { return tlsClientProtocol.getOutputStream(); }
- @Override public synchronized void close() throws IOException { tlsClientProtocol.close(); }
- @Override public void addHandshakeCompletedListener( HandshakeCompletedListener arg0) { }
- @Override public boolean getEnableSessionCreation() { return false; }
- @Override public String[] getEnabledCipherSuites() { return null; }
- @Override public String[] getEnabledProtocols() { return null; }
- @Override public boolean getNeedClientAuth() { return false; }
-
- @Override
- public SSLSession getSession() {
- return new SSLSession() {
-
- /*原本这些方法都是直接throw UnsupportedOperationException 导致看不到真实异常*/
- @Override
- public int getApplicationBufferSize() {
- return 0;
- }
- @Override public String getCipherSuite() { return null; }
- @Override public long getCreationTime() { return 0; }
- @Override public byte[] getId() { return null; }
- @Override public long getLastAccessedTime() { return 0; }
- @Override public java.security.cert.Certificate[] getLocalCertificates() { return null; }
- @Override public Principal getLocalPrincipal() { return null; }
- @Override public int getPacketBufferSize() { return 0; }
- @Override public X509Certificate[] getPeerCertificateChain() throws SSLPeerUnverifiedException { return null; }
- @Override public java.security.cert.Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException { return peertCerts; }
- @Override public String getPeerHost() { return null; }
- @Override public int getPeerPort() { return 0; }
- @Override public Principal getPeerPrincipal() throws SSLPeerUnverifiedException { return null; }
- @Override public String getProtocol() { return null; }
- @Override public SSLSessionContext getSessionContext() { return null; }
- @Override public Object getValue(String arg0) { return null; }
- @Override public String[] getValueNames() { return null; }
- @Override public void invalidate() { return; }
- @Override public boolean isValid() { return true; }
- @Override public void putValue(String arg0, Object arg1) { return; }
- @Override
- public void removeValue(String arg0) {
- return;
- }
- };
- }
-
- @Override public String[] getSupportedProtocols() { return null; }
- @Override public boolean getUseClientMode() { return false; }
- @Override public boolean getWantClientAuth() { return false; }
- @Override public void removeHandshakeCompletedListener(HandshakeCompletedListener arg0) { }
- @Override public void setEnableSessionCreation(boolean arg0) { }
- @Override public void setEnabledCipherSuites(String[] arg0) { }
- @Override public void setEnabledProtocols(String[] arg0) { }
- @Override public void setNeedClientAuth(boolean arg0) { }
- @Override public void setUseClientMode(boolean arg0) { }
- @Override public void setWantClientAuth(boolean arg0) { }
- @Override public String[] getSupportedCipherSuites() { return null; }
-
- @Override
- public void startHandshake() throws IOException {
- tlsClientProtocol.connect(new DefaultTlsClient() {
-
- @SuppressWarnings("unchecked")
- @Override
- public Hashtable<Integer, byte[]> getClientExtensions() throws IOException {
- Hashtable<Integer, byte[]> clientExtensions = super.getClientExtensions();
- if (clientExtensions == null) {
- clientExtensions = new Hashtable<Integer, byte[]>();
- }
-
- //Add host_name
- byte[] host_name = host.getBytes();
-
- final ByteArrayOutputStream baos = new ByteArrayOutputStream();
- final DataOutputStream dos = new DataOutputStream(baos);
- dos.writeShort(host_name.length + 3);
- dos.writeByte(0);
- dos.writeShort(host_name.length);
- dos.write(host_name);
- dos.close();
- clientExtensions.put(ExtensionType.server_name, baos.toByteArray());
- return clientExtensions;
- }
-
- @Override
- public TlsAuthentication getAuthentication() throws IOException {
- return new TlsAuthentication() {
-
- @Override
- public void notifyServerCertificate(Certificate serverCertificate) throws IOException {
- try {
- KeyStore ks = _loadKeyStore();
-
- CertificateFactory cf = CertificateFactory.getInstance("X.509");
- List<java.security.cert.Certificate> certs = new LinkedList<java.security.cert.Certificate>();
- boolean trustedCertificate = false;
- for ( org.bouncycastle.asn1.x509.Certificate c : serverCertificate.getCertificateList()) {
- java.security.cert.Certificate cert = cf.generateCertificate(new ByteArrayInputStream(c.getEncoded()));
- certs.add(cert);
-
- String alias = ks.getCertificateAlias(cert);
- if(alias != null) {
- if (cert instanceof java.security.cert.X509Certificate) {
- try {
- ( (java.security.cert.X509Certificate) cert).checkValidity();
- trustedCertificate = true;
- } catch(CertificateExpiredException cee) {
- // Accept all the certs!
- }
- }
- } else {
- // Accept all the certs!
- }
-
- }
- if (!trustedCertificate) {
- // Accept all the certs!
- }
- peertCerts = certs.toArray(new java.security.cert.Certificate[0]);
- } catch (Exception ex) {
- ex.printStackTrace();
- throw new IOException(ex);
- }
- }
-
- @Override
- public TlsCredentials getClientCredentials(CertificateRequest certificateRequest) throws IOException {
- return null;
- }
-
- private KeyStore _loadKeyStore() throws Exception {
- FileInputStream trustStoreFis = null;
- try {
- KeyStore localKeyStore = null;
-
- String trustStoreType = System.getProperty("javax.net.ssl.trustStoreType")!=null?System.getProperty("javax.net.ssl.trustStoreType"):KeyStore.getDefaultType();
- String trustStoreProvider = System.getProperty("javax.net.ssl.trustStoreProvider")!=null?System.getProperty("javax.net.ssl.trustStoreProvider"):"";
-
- if (trustStoreType.length() != 0) {
- if (trustStoreProvider.length() == 0) {
- localKeyStore = KeyStore.getInstance(trustStoreType);
- } else {
- localKeyStore = KeyStore.getInstance(trustStoreType, trustStoreProvider);
- }
-
- char[] keyStorePass = null;
- String str5 = System.getProperty("javax.net.ssl.trustStorePassword")!=null?System.getProperty("javax.net.ssl.trustStorePassword"):"";
-
- if (str5.length() != 0) {
- keyStorePass = str5.toCharArray();
- }
-
- localKeyStore.load(trustStoreFis, keyStorePass);
-
- if (keyStorePass != null) {
- for (int i = 0; i < keyStorePass.length; i++) {
- keyStorePass[i] = 0;
- }
- }
- }
- return localKeyStore;
- } finally {
- if (trustStoreFis != null) {
- trustStoreFis.close();
- }
- }
- }
- };
- }
-
- });
- } // startHandshake
- };
- }
- }
类:TLSSocketConnectionFactory
依赖jar包:
然后再写一个httpsConnectionUtils工具类:
- package com.mln.frame;
-
- import java.io.BufferedReader;
- import java.io.DataOutputStream;
- import java.io.InputStreamReader;
- import java.net.URL;
- import java.net.URLEncoder;
- import java.security.cert.CertificateException;
- import java.security.cert.X509Certificate;
- import java.util.ArrayList;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Map;
-
- import javax.net.ssl.HostnameVerifier;
- import javax.net.ssl.HttpsURLConnection;
- import javax.net.ssl.SSLContext;
- import javax.net.ssl.SSLSession;
- import javax.net.ssl.TrustManager;
- import javax.net.ssl.X509TrustManager;
-
- import org.apache.commons.lang.StringUtils;
-
- /**
- * 本类是解决https访问问题
- * @author sun
- *
- */
- public class HttpsConnectUtils {
-
- /**
- * 获取url内容
- */
- public static String getQuery(String desUrl,String method,Map<String,String> params) throws Throwable{
- if(!"POST".equalsIgnoreCase(method)){
- method="GET";//如果不是POST就认为是GET,至于PUT很少用到,暂时用不到
- }
- String paramStr="";
- if(params!=null && !params.isEmpty()){
- List<String> list=new ArrayList<String>();//存放参数
- Iterator<String> it=params.keySet().iterator();
- while(it.hasNext()){
- String key=it.next();
- list.add(key+"="+URLEncoder.encode(params.get(key), "utf-8"));
- }
- paramStr=StringUtils.join(list,"&");
- }
- //如果是get请求且带有参数
- if(!"".equals(paramStr) && "GET".equalsIgnoreCase(method)){
- desUrl+="?"+paramStr;
- }
- URL url = new URL(null,desUrl,new sun.net.www.protocol.https.Handler());
- SSLContext sslContext=SSLContext.getInstance("TLS");
- TrustManager x509TrustManager=new X509TrustManager() {
-
- @Override
- public X509Certificate[] getAcceptedIssuers() {
- return null;
- }
-
- @Override
- public void checkServerTrusted(X509Certificate[] arg0, String arg1)
- throws CertificateException {
-
- }
-
- @Override
- public void checkClientTrusted(X509Certificate[] arg0, String arg1)
- throws CertificateException {
-
- }
- };
- sslContext.init(null, new TrustManager[]{x509TrustManager}, null);
- HttpsURLConnection httpsConn=(HttpsURLConnection) url.openConnection();
- httpsConn.setSSLSocketFactory(new TLSSocketConnectionFactory());
- httpsConn.setRequestProperty("accept", "*/*");
- httpsConn.setRequestProperty("connection", "Keep-Alive");
- httpsConn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows xp)");
- httpsConn.setDoOutput(true);
- httpsConn.setDoInput(true);
- httpsConn.setRequestMethod(method!=null?method:"GET");//默认get
- //忽略证书设置
- httpsConn.setHostnameVerifier(new HostnameVerifier() {
- @Override
- public boolean verify(String arg0, SSLSession arg1) {
- return true;
- }
- });
- //下面的方法会自动修改请求方式为POST
- if(!"".equals(paramStr) && "POST".equalsIgnoreCase(method)){
- DataOutputStream out = new DataOutputStream(httpsConn.getOutputStream());
- out.writeBytes(paramStr);
- out.flush();
- out.close();
- }
-
- InputStreamReader isr = new InputStreamReader(httpsConn.getInputStream(), "utf-8");
- BufferedReader inReader = new BufferedReader(isr);
- StringBuffer result = new StringBuffer();
- String inputLine;
- while ((inputLine = inReader.readLine()) != null) {
- result.append(inputLine);
- }
- // 关闭输入流
- inReader.close();
- isr.close();
- httpsConn.disconnect();//每次请求完毕后关闭链接
- return result.toString();
- }
- }
调用的时候直接按httpsConnectionUtils.getQuery(String desUrl,String method,Map<String,String> params)调用即可。
-----------------------------------------------------------------------
以下为jdk1.8版的工具类,也发下相关的httpsConnectionUtils工具类,如下:
- package com.mln.frame;
-
- import java.io.BufferedReader;
- import java.io.DataOutputStream;
- import java.io.InputStreamReader;
- import java.net.URL;
- import java.net.URLEncoder;
- import java.security.cert.CertificateException;
- import java.security.cert.X509Certificate;
- import java.util.ArrayList;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Map;
-
- import javax.net.ssl.HostnameVerifier;
- import javax.net.ssl.HttpsURLConnection;
- import javax.net.ssl.SSLContext;
- import javax.net.ssl.SSLSession;
- import javax.net.ssl.TrustManager;
- import javax.net.ssl.X509TrustManager;
-
- import org.apache.commons.lang.StringUtils;
-
- /**
- * 本类是解决https访问问题
- * @author sun
- *
- */
- public class HttpsConnectUtils {
-
- /**
- * 获取url内容
- */
- public static String getQuery(String desUrl,String method,Map<String,String> params) throws Throwable{
- if(!"POST".equalsIgnoreCase(method)){
- method="GET";//如果不是POST就认为是GET,至于PUT很少用到,暂时用不到
- }
- String paramStr="";
- if(params!=null && !params.isEmpty()){
- List<String> list=new ArrayList<String>();//存放参数
- Iterator<String> it=params.keySet().iterator();
- while(it.hasNext()){
- String key=it.next();
- list.add(key+"="+URLEncoder.encode(params.get(key), "utf-8"));
- }
- paramStr=StringUtils.join(list,"&");
- }
- //如果是get请求且带有参数
- if(!"".equals(paramStr) && "GET".equalsIgnoreCase(method)){
- desUrl+="?"+paramStr;
- }
- URL url = new URL(null,desUrl,new sun.net.www.protocol.https.Handler());
- SSLContext sslContext=SSLContext.getInstance("TLSv1.2");//jdk8支持1.2版本
- TrustManager x509TrustManager=new X509TrustManager() {
-
- @Override
- public X509Certificate[] getAcceptedIssuers() {
- return null;
- }
-
- @Override
- public void checkServerTrusted(X509Certificate[] arg0, String arg1)
- throws CertificateException {
-
- }
-
- @Override
- public void checkClientTrusted(X509Certificate[] arg0, String arg1)
- throws CertificateException {
-
- }
- };
- sslContext.init(null, new TrustManager[]{x509TrustManager}, null);
- HttpsURLConnection httpsConn=(HttpsURLConnection) url.openConnection();
- httpsConn.setSSLSocketFactory(sslContext.getSocketFactory());
- httpsConn.setRequestProperty("accept", "*/*");
- httpsConn.setRequestProperty("connection", "Keep-Alive");
- httpsConn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows xp)");
- httpsConn.setDoOutput(true);
- httpsConn.setDoInput(true);
- httpsConn.setRequestMethod(method!=null?method:"GET");//默认get
- //忽略证书设置
- httpsConn.setHostnameVerifier(new HostnameVerifier() {
- @Override
- public boolean verify(String arg0, SSLSession arg1) {
- return true;
- }
- });
- //下面的方法会自动修改请求方式为POST
- if(!"".equals(paramStr) && "POST".equalsIgnoreCase(method)){
- DataOutputStream out = new DataOutputStream(httpsConn.getOutputStream());
- out.writeBytes(paramStr);
- out.flush();
- out.close();
- }
-
- InputStreamReader isr = new InputStreamReader(httpsConn.getInputStream(), "utf-8");
- BufferedReader inReader = new BufferedReader(isr);
- StringBuffer result = new StringBuffer();
- String inputLine;
- while ((inputLine = inReader.readLine()) != null) {
- result.append(inputLine);
- }
- // 关闭输入流
- inReader.close();
- isr.close();
- httpsConn.disconnect();//每次请求完毕后关闭链接
- return result.toString();
- }
- }
希望能帮到和我一样苦逼的人!
总相比来说升级jdk肯定是最好方案,不得以才会用上面方法,也感谢其他善于分享经验的人!
--------------------------追加------------
我又采用了另外一种方式,直接升级jdk,但是报错(PKIX:unable to find valid certification path to requested target),后来检查发现,是无法检查到证书导致的,于是通过下载ssl证书,导入到jdk中,重启服务,完美运行。
运行-cmd-cd到%JAVA_HOME%\jre\lib\security\运行以下命令:
keytool -import -file f:\ca.crt -keystore "%JAVA_HOME%\jre\lib\security\cacerts" -alias certServer
注释:
-file f:\ca.crt 证书所在路径
-keystore cacerts ,应该指定全路径 -keystore "%JAVA_HOME%/jre/lib/security/cacerts";
-alias certServer ,certServer为证书别名,确保唯一
如果发现在执行命令时报错 “keytool不是指定的命令” 错误,请cd到%JAVA_HOME%/jre/bin目录下执行命令。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。