Browse Source

1:修改之前错误的Https检验工具。

guiying712 8 years ago
parent
commit
f53f1a16cc

+ 1 - 1
common/src/main/java/com/guiying/common/base/BaseApplication.java

@@ -115,7 +115,7 @@ public class BaseApplication extends Application {
             //杀死后台进程需要在AndroidManifest中声明android.permission.KILL_BACKGROUND_PROCESSES;
             ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
             activityManager.killBackgroundProcesses(context.getPackageName());
-            System.exit(0);
+            //System.exit(0);
         } catch (Exception e) {
             Log.e("ActivityManager", "app exit" + e.getMessage());
         }

+ 3 - 2
common/src/main/java/com/guiying/common/http/HttpClient.java

@@ -38,6 +38,7 @@ public class HttpClient {
 
     /*The certificate's password*/
     private static final String STORE_PASS = "4444444";
+    private static final String STORE_ALIAS = "4444444";
     /*返回数据为String*/
     public static final int STRING = 0;
     /*返回数据为json对象*/
@@ -74,11 +75,11 @@ public class HttpClient {
 
     private HttpClient() {
         ClearableCookieJar cookieJar = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(Utils.getContext()));
-        //HttpsUtil.SSLParams sslParams = HttpsUtil.getSslSocketFactory(Utils.getContext(), new int[0], , STORE_PASS);
+        //HttpsUtil.SSLParams sslParams = HttpsUtil.getSslSocketFactory(Utils.getContext(), R.raw.cer,STORE_PASS , STORE_ALIAS);
         okHttpClient = new OkHttpClient.Builder()
                 .connectTimeout(10000L, TimeUnit.MILLISECONDS)
                 //.sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)
-                .hostnameVerifier(HttpsUtil.getHostnameVerifier())
+                // .hostnameVerifier(HttpsUtil.getHostnameVerifier())
                 .addInterceptor(new LoggerInterceptor(null, true))
                 .cookieJar(cookieJar)
                 .build();

+ 0 - 296
common/src/main/java/com/guiying/common/http/HttpsUtil.java

@@ -1,296 +0,0 @@
-package com.guiying.common.http;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.os.Build;
-import android.support.annotation.RawRes;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.InetAddress;
-import java.net.Socket;
-import java.net.UnknownHostException;
-import java.security.KeyManagementException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.UnrecoverableKeyException;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.KeyManager;
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509TrustManager;
-
-/**
- * HttpsUtils来自于鸿洋的: https://github.com/hongyangAndroid/okhttputils;
- * 增加了主机名校验方法getHostnameVerifier();
- * 其他参考的文章有:http://android.jobbole.com/83787/;
- *
- * Android 4.X 对TLS1.1、TLS1.2的支持参考了http://blog.csdn.net/joye123/article/details/53888252
- */
-public class HttpsUtil {
-
-    /**
-     * 包装的 SSL(Secure Socket Layer)参数类
-     */
-    public static class SSLParams {
-        public SSLSocketFactory sSLSocketFactory;
-        public X509TrustManager trustManager;
-    }
-
-    /**
-     * @param context        上下文
-     * @param certificatesId "XXX.cer" 文件 (文件位置res/raw/XXX.cer)
-     * @param bksFileId      "XXX.bks"文件(文件位置res/raw/XXX.bks)
-     * @param password       The certificate's password.
-     * @return SSLParams
-     */
-    public static SSLParams getSslSocketFactory(Context context, @RawRes int[] certificatesId, @RawRes int bksFileId, String password) {
-        if (context == null) {
-            throw new NullPointerException("context == null");
-        }
-        SSLParams sslParams = new SSLParams();
-        try {
-            TrustManager[] trustManagers = prepareTrustManager(context, certificatesId);
-            KeyManager[] keyManagers = prepareKeyManager(context, bksFileId, password);
-
-            //创建TLS类型的SSLContext对象,that uses our TrustManager
-            SSLContext sslContext = SSLContext.getInstance("TLS");
-
-            X509TrustManager x509TrustManager;
-            if (trustManagers != null) {
-                x509TrustManager = new MyTrustManager(chooseTrustManager(trustManagers));
-            } else {
-                x509TrustManager = new UnSafeTrustManager();
-            }
-            //用上面得到的trustManagers初始化SSLContext,这样sslContext就会信任keyStore中的证书
-            sslContext.init(keyManagers, new TrustManager[]{x509TrustManager}, null);
-
-            //通过sslContext获取SSLSocketFactory对象
-            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
-                /*Android 4.X 对TLS1.1、TLS1.2的支持*/
-                sslParams.sSLSocketFactory = new Tls12SocketFactory(sslContext.getSocketFactory());
-                sslParams.trustManager = x509TrustManager;
-                return sslParams;
-            }
-
-            sslParams.sSLSocketFactory = sslContext.getSocketFactory();
-            sslParams.trustManager = x509TrustManager;
-            return sslParams;
-        } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
-            throw new AssertionError(e);
-        }
-    }
-
-
-    /**
-     * 主机名校验方法
-     */
-    public static HostnameVerifier getHostnameVerifier() {
-        return new HostnameVerifier() {
-            @Override
-            public boolean verify(String hostname, SSLSession session) {
-                return hostname.equalsIgnoreCase(session.getPeerHost());
-            }
-        };
-    }
-
-
-    private static TrustManager[] prepareTrustManager(Context context, int[] certificatesId) {
-        if (certificatesId == null || certificatesId.length <= 0) {
-            return null;
-        }
-
-        try {
-            //创建X.509格式的CertificateFactory
-            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
-            // 创建一个默认类型的KeyStore,存储我们信任的证书
-            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
-            keyStore.load(null);
-            int index = 0;
-            for (int certificateId : certificatesId) {
-                //从本地资源中获取证书的流
-                InputStream cerInputStream = context.getResources().openRawResource(certificateId);
-                String certificateAlias = Integer.toString(index++);
-
-                //certificate是java.security.cert.Certificate,而不是其他Certificate
-                //证书工厂根据证书文件的流生成证书Certificate
-                Certificate certificate = certificateFactory.generateCertificate(cerInputStream);
-                //将证书certificate作为信任的证书放入到keyStore中
-                keyStore.setCertificateEntry(certificateAlias, certificate);
-                try {
-                    if (cerInputStream != null)
-                        cerInputStream.close();
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
-            }
-
-            //TrustManagerFactory是用于生成TrustManager的,这里创建一个默认类型的TrustManagerFactory
-            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
-            //用我们之前的keyStore实例初始化TrustManagerFactory,这样trustManagerFactory就会信任keyStore中的证书
-            trustManagerFactory.init(keyStore);
-            return trustManagerFactory.getTrustManagers();
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        return null;
-    }
-
-
-    private static KeyManager[] prepareKeyManager(Context context, @RawRes int bksFileId, String password) {
-
-        try {
-            KeyStore clientKeyStore = KeyStore.getInstance("BKS");
-            clientKeyStore.load(context.getResources().openRawResource(bksFileId), password.toCharArray());
-            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
-            keyManagerFactory.init(clientKeyStore, password.toCharArray());
-            return keyManagerFactory.getKeyManagers();
-
-        } catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException | CertificateException | IOException e) {
-            e.printStackTrace();
-        }
-        return null;
-    }
-
-
-    private static X509TrustManager chooseTrustManager(TrustManager[] trustManagers) {
-        for (TrustManager trustManager : trustManagers) {
-            if (trustManager instanceof X509TrustManager) {
-                return (X509TrustManager) trustManager;
-            }
-        }
-        return null;
-    }
-
-
-    /**
-     * 客户端不对证书做任何检查;
-     * 客户端不对证书做任何验证的做法有很大的安全漏洞。
-     */
-    private static class UnSafeTrustManager implements X509TrustManager {
-
-        @SuppressLint("TrustAllX509TrustManager")
-        @Override
-        public void checkClientTrusted(X509Certificate[] chain, String authType)
-                throws CertificateException {
-        }
-
-        @SuppressLint("TrustAllX509TrustManager")
-        @Override
-        public void checkServerTrusted(X509Certificate[] chain, String authType)
-                throws CertificateException {
-        }
-
-        @Override
-        public X509Certificate[] getAcceptedIssuers() {
-            return new X509Certificate[]{};
-        }
-    }
-
-
-    private static class MyTrustManager implements X509TrustManager {
-        private X509TrustManager defaultTrustManager;
-        private X509TrustManager localTrustManager;
-
-        private MyTrustManager(X509TrustManager localTrustManager) throws NoSuchAlgorithmException, KeyStoreException {
-            //TrustManagerFactory是用于生成TrustManager的,创建一个默认类型的TrustManagerFactory
-            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
-            trustManagerFactory.init((KeyStore) null);
-            defaultTrustManager = chooseTrustManager(trustManagerFactory.getTrustManagers());
-            this.localTrustManager = localTrustManager;
-        }
-
-
-        @SuppressLint("TrustAllX509TrustManager")
-        @Override
-        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
-
-        }
-
-        @Override
-        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
-            try {
-                defaultTrustManager.checkServerTrusted(chain, authType);
-            } catch (CertificateException ce) {
-                localTrustManager.checkServerTrusted(chain, authType);
-            }
-        }
-
-
-        @Override
-        public X509Certificate[] getAcceptedIssuers() {
-            return new X509Certificate[0];
-        }
-    }
-
-
-    /**
-     * 自行实现SSLSocketFactory ,实现Android 4.X 对TLSv1.1、TLSv1.2的支持
-     */
-    private static class Tls12SocketFactory extends SSLSocketFactory {
-
-        private static final String[] TLS_SUPPORT_VERSION = {"TLSv1.1", "TLSv1.2"};
-
-        final SSLSocketFactory delegate;
-
-        private Tls12SocketFactory(SSLSocketFactory base) {
-            this.delegate = base;
-        }
-
-        @Override
-        public String[] getDefaultCipherSuites() {
-            return delegate.getDefaultCipherSuites();
-        }
-
-        @Override
-        public String[] getSupportedCipherSuites() {
-            return delegate.getSupportedCipherSuites();
-        }
-
-        @Override
-        public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
-            return patch(delegate.createSocket(s, host, port, autoClose));
-        }
-
-        @Override
-        public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
-            return patch(delegate.createSocket(host, port));
-        }
-
-        @Override
-        public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
-            return patch(delegate.createSocket(host, port, localHost, localPort));
-        }
-
-        @Override
-        public Socket createSocket(InetAddress host, int port) throws IOException {
-            return patch(delegate.createSocket(host, port));
-        }
-
-        @Override
-        public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
-            return patch(delegate.createSocket(address, port, localAddress, localPort));
-        }
-
-        private Socket patch(Socket s) {
-            //代理SSLSocketFactory在创建一个Socket连接的时候,会设置Socket的可用的TLS版本。
-            if (s instanceof SSLSocket) {
-                ((SSLSocket) s).setEnabledProtocols(TLS_SUPPORT_VERSION);
-            }
-            return s;
-        }
-    }
-
-
-}

+ 263 - 0
common/src/main/java/com/guiying/common/http/HttpsUtils.java

@@ -0,0 +1,263 @@
+package com.guiying.common.http;
+
+import android.content.Context;
+import android.support.annotation.RawRes;
+import android.text.TextUtils;
+
+import com.guiying.common.utils.CloseUtils;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.security.InvalidKeyException;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SecureRandom;
+import java.security.SignatureException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * <p>Https证书校验工具类</p>
+ *
+ * @author 张华洋 2017/5/11 16:14
+ * @version V1.2.0
+ * @name HttpsUtils
+ */
+public class HttpsUtils {
+
+
+    public static class SSLParams {
+        public SSLSocketFactory sSLSocketFactory;
+        public X509TrustManager trustManager;
+    }
+
+    /**
+     * @param context   上下文
+     * @param bksFileId "XXX.bks"文件(文件位置res/raw/XXX.bks)
+     * @param password  The certificate's password.
+     * @return SSLParams
+     */
+    public static SSLParams getSslSocketFactory(Context context, @RawRes int bksFileId, String password, String alias) {
+        if (context == null) {
+            throw new NullPointerException("context == null");
+        }
+        if (TextUtils.isEmpty(password) || TextUtils.isEmpty(alias)) {
+            throw new NullPointerException("password == null or alias == null!");
+        }
+        SSLParams sslParams = new SSLParams();
+        try {
+            // 创建一个BKS类型的KeyStore,存储我们信任的证书
+            KeyStore clientKeyStore = KeyStore.getInstance("BKS");
+            clientKeyStore.load(context.getResources().openRawResource(bksFileId), password.toCharArray());
+            //通过alias直接从密钥库中读取证书
+            Certificate rootCA = clientKeyStore.getCertificate(alias);
+            // Turn it to X509 format.
+            InputStream certInput = new ByteArrayInputStream(rootCA.getEncoded());
+            X509Certificate serverCert = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(certInput);
+            //关闭流
+            CloseUtils.closeIO(certInput);
+
+            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+            //用我们之前的keyStore实例初始化TrustManagerFactory,这样trustManagerFactory就会信任keyStore中的证书
+            trustManagerFactory.init(clientKeyStore);
+
+            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+            keyManagerFactory.init(clientKeyStore, password.toCharArray());
+
+            X509TrustManager x509TrustManager = new SafeTrustManager(serverCert);
+
+            //创建TLS类型的SSLContext对象,that uses our TrustManager
+            SSLContext sslContext = SSLContext.getInstance("TLS");
+
+            //用上面得到的trustManagers初始化SSLContext,这样sslContext就会信任keyStore中的证书
+            sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
+
+            //Android 4.X 对TLS1.1、TLS1.2的支持
+            sslParams.sSLSocketFactory = new Tls12SocketFactory(sslContext.getSocketFactory());
+            sslParams.trustManager = x509TrustManager;
+            return sslParams;
+        } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException | IOException | CertificateException e) {
+            throw new AssertionError(e);
+        }
+    }
+
+    /**
+     * 不做证书校验,信任所有证书
+     */
+    public static SSLParams getSslSocketFactoryUnsafe() {
+        SSLParams sslParams = new SSLParams();
+        try {
+            X509TrustManager x509TrustManager = new UnSafeTrustManager();
+
+            //创建TLS类型的SSLContext对象,that uses our TrustManager
+            SSLContext sslContext = SSLContext.getInstance("TLS");
+
+            //用上面得到的trustManagers初始化SSLContext,这样sslContext就会信任keyStore中的证书
+            sslContext.init(null, new TrustManager[]{x509TrustManager}, null);
+
+            //Android 4.X 对TLS1.1、TLS1.2的支持
+            sslParams.sSLSocketFactory = new Tls12SocketFactory(sslContext.getSocketFactory());
+            sslParams.trustManager = x509TrustManager;
+            return sslParams;
+        } catch (NoSuchAlgorithmException | KeyManagementException e) {
+            throw new AssertionError(e);
+        }
+    }
+
+
+    /**
+     * 主机名校验方法
+     */
+    public static HostnameVerifier getHostnameVerifier() {
+        return new HostnameVerifier() {
+            @Override
+            public boolean verify(String hostname, SSLSession session) {
+                return hostname.equalsIgnoreCase(session.getPeerHost());
+            }
+        };
+    }
+
+
+    /**
+     * 对服务器证书域名进行强校验
+     */
+    private static class SafeTrustManager implements X509TrustManager {
+        private X509Certificate mCertificate;
+
+        private SafeTrustManager(X509Certificate serverCert) {
+            mCertificate = serverCert;
+        }
+
+        @Override
+        public void checkClientTrusted(X509Certificate[] x509Certificates, String authType) throws CertificateException {
+
+        }
+
+        @Override
+        public void checkServerTrusted(X509Certificate[] x509Certificates, String authType) throws CertificateException {
+            if (x509Certificates == null) {
+                throw new IllegalArgumentException("Check Server x509Certificates is null");
+            }
+
+            if (x509Certificates.length < 0) {
+                throw new IllegalArgumentException("Check Server x509Certificates is empty");
+            }
+
+            try {
+                for (X509Certificate cert : x509Certificates) {
+                    // Make sure that it hasn't expired.
+                    cert.checkValidity();
+                    //和App预埋的证书做对比
+                    cert.verify(mCertificate.getPublicKey());
+                }
+            } catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchProviderException | SignatureException e) {
+                e.printStackTrace();
+            }
+        }
+
+        @Override
+        public X509Certificate[] getAcceptedIssuers() {
+            return new X509Certificate[0];
+        }
+    }
+
+
+    /**
+     * 客户端不对证书做任何验证的做法有很大的安全漏洞。
+     */
+    private static class UnSafeTrustManager implements X509TrustManager {
+
+        @Override
+        public void checkClientTrusted(X509Certificate[] chain, String authType)
+                throws CertificateException {
+        }
+
+        @Override
+        public void checkServerTrusted(X509Certificate[] chain, String authType)
+                throws CertificateException {
+        }
+
+        @Override
+        public X509Certificate[] getAcceptedIssuers() {
+            return new X509Certificate[]{};
+        }
+    }
+
+
+    /**
+     * 自定义SSLSocketFactory ,实现Android 4.X 对TLSv1.1、TLSv1.2的支持
+     */
+    private static class Tls12SocketFactory extends SSLSocketFactory {
+
+        private static final String[] TLS_SUPPORT_VERSION = {"TLSv1.1", "TLSv1.2"};
+
+        final SSLSocketFactory delegate;
+
+        private Tls12SocketFactory(SSLSocketFactory base) {
+            this.delegate = base;
+        }
+
+        @Override
+        public String[] getDefaultCipherSuites() {
+            return delegate.getDefaultCipherSuites();
+        }
+
+        @Override
+        public String[] getSupportedCipherSuites() {
+            return delegate.getSupportedCipherSuites();
+        }
+
+        @Override
+        public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
+            return patch(delegate.createSocket(s, host, port, autoClose));
+        }
+
+        @Override
+        public Socket createSocket(String host, int port) throws IOException {
+            return patch(delegate.createSocket(host, port));
+        }
+
+        @Override
+        public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
+            return patch(delegate.createSocket(host, port, localHost, localPort));
+        }
+
+        @Override
+        public Socket createSocket(InetAddress host, int port) throws IOException {
+            return patch(delegate.createSocket(host, port));
+        }
+
+        @Override
+        public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
+            return patch(delegate.createSocket(address, port, localAddress, localPort));
+        }
+
+        private Socket patch(Socket s) {
+            //代理SSLSocketFactory在创建一个Socket连接的时候,会设置Socket的可用的TLS版本。
+            if (s instanceof SSLSocket) {
+                ((SSLSocket) s).setEnabledProtocols(TLS_SUPPORT_VERSION);
+            }
+            return s;
+        }
+    }
+
+}