• Jdk1.6 HTTPS访问问题解决办法


    真是艹蛋的一次经历,jdk6上面去访问别人的https,还好有百度搞定了问题.现在写下随笔,记录下;

    首先要自己重写SSLSocketFactory这个类,

    下面是自己重写的这个类:TLSSocketConnectionFactory

    package cn.cbsw.tools;
    
    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
            };
        }
    }

    依赖jar包:

    bcpkix-jdk15on-1.60.jar

    bcprov-jdk15on-1.60.jar

    然后再写一个httpsConnectionUtils工具类:

    package cn.cbsw.tools;
    
    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 cn.cbsw.tools;
    
    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到1.8肯定是最好方案,不得以才会用上面方法.

    也感谢那些善于分享经验的人!

  • 相关阅读:
    移动端开发rem布局之less+媒体查询布局的原理步骤和心得
    前端实现文件下载方式总汇
    如何能提高CSS编写技巧?提高Web前端开发效率
    常用的CSS命名规则
    CSS背景background
    CSS盒子模型
    简单的树形菜单如何写?
    彻底掌握css动画【transition】
    首页白屏优化实践
    我来聊聊面向模板的前端开发
  • 原文地址:https://www.cnblogs.com/syj2016/p/13501454.html
Copyright © 2020-2023  润新知