您的应用使用 Apache HTTP 客户端的 X509TrustManager 接口的不安全实现

Your app is using an unsafe implementation of the X509TrustManager interface with an Apache HTTP client

我的应用程序中有以下代码 -

public class MySSLSocketFactory extends SSLSocketFactory {
    SSLContext sslContext = SSLContext.getInstance("TLS");

    public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
        super(truststore);

        TrustManager tm = new X509TrustManager() {
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

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

            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };

        sslContext.init(null, new TrustManager[] { tm }, null);
    }

    @Override
    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
        return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
    }

    @Override
    public Socket createSocket() throws IOException {
        return sslContext.getSocketFactory().createSocket();
    }


public static HttpClient getNewHttpClient() {
    try {
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        trustStore.load(null, null);

        SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
        sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        HttpParams params = new BasicHttpParams();


        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        registry.register(new Scheme("https", sf, 443));

        ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

        return new DefaultHttpClient(ccm, params);
    } catch (Exception e) {
        return new DefaultHttpClient();
    }
 }


}

但是,Google Play 商店拒绝了我的应用程序。 指定原因 -

Your app is using an unsafe implementation of the X509TrustManager interface with an Apache HTTP client, resulting in a security vulnerability. Please see this Google Help Center article for details, including the deadline for fixing the vulnerability.

所以,为了摆脱这个。我尝试从网站下载证书,并尝试通过以下代码使用它,instead of the above one -

public class MyHttpClient extends DefaultHttpClient {

    private static Context context;

    public static void setContext(Context context) {
        MyHttpClient.context = context;
    }

    public MyHttpClient(HttpParams params) {
        super(params);
    }
    public MyHttpClient(Context ctx) {
        context = ctx;

    }
    public MyHttpClient(ClientConnectionManager httpConnectionManager, HttpParams params) {
        super(httpConnectionManager, params);
    }

    @Override
    protected ClientConnectionManager createClientConnectionManager() {
        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        // Register for port 443 our SSLSocketFactory with our keystore
        // to the ConnectionManager
        try {
            registry.register(new Scheme("https", getSSLSocketFactory(), 443));
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (UnrecoverableKeyException e) {
            e.printStackTrace();
        }
        return new SingleClientConnManager(getParams(), registry);
    }

    public static org.apache.http.conn.ssl.SSLSocketFactory getSSLSocketFactory()
            throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException, KeyManagementException, UnrecoverableKeyException {
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        InputStream caInput = context.getResources().openRawResource(R.raw.dummy_certificate); // this cert file stored in \app\src\main\res\raw folder path

        Certificate ca = cf.generateCertificate(caInput);
        caInput.close();

        KeyStore keyStore = KeyStore.getInstance("BKS");
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);

        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);

           getWrappedTrustManagers(tmf.getTrustManagers());

        org.apache.http.conn.ssl.SSLSocketFactory sf=new SSLSocketFactory(keyStore);
        sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);

        return sf;
    }




    public static TrustManager[] getWrappedTrustManagers(TrustManager[] trustManagers) {
        final X509TrustManager originalTrustManager = (X509TrustManager) trustManagers[0];
        return new TrustManager[]{
                new X509TrustManager() {
                    public X509Certificate[] getAcceptedIssuers() {
                        return originalTrustManager.getAcceptedIssuers();
                    }

                    public void checkClientTrusted(X509Certificate[] certs, String authType) {
                        try {
                            if (certs != null && certs.length > 0) {
                                certs[0].checkValidity();
                            } else {
                                originalTrustManager.checkClientTrusted(certs, authType);
                            }
                        } catch (CertificateException e) {
                            Log.w("checkClientTrusted", e.toString());
                        }
                    }

                    public void checkServerTrusted(X509Certificate[] certs, String authType) {
                        try {
                            if (certs != null && certs.length > 0) {
                                certs[0].checkValidity();
                            } else {
                                originalTrustManager.checkServerTrusted(certs, authType);
                            }
                        } catch (CertificateException e) {
                            Log.w("checkServerTrusted", e.toString());
                        }
                    }
                }
        };
    }
    }

并将其命名为 -

DefaultHttpClient client = new MyHttpClient(App.getContext());

但是,现在出现异常 -

javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
at com.android.org.conscrypt.SSLNullSession.getPeerCertificates(SSLNullSession.java:104)
[gralloc_lock]: new usage 0x933
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:93)
at org.apache.http.conn.ssl.SSLSocketFactory.createSocket(SSLSocketFactory.java:388)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:165)
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
at com.example.http.HTTPPost.executeRequest(HTTPPost.java:336)
at com.example.http.HTTPPost.callHttpRequest(HTTPPost.java:301)
11-17 18:19:57.788 7548-7548/com.savelife I/brcm-gr: [gralloc_lock]: new usage 0x933
at com.example.http.HTTPPost.doInBackground(HTTPPost.java:286)
at com.example.http.HTTPPost.doInBackground(HTTPPost.java:67)
at android.os.AsyncTask.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)

应用Gradle文件

apply plugin: 'com.android.application'
android {
    compileSdkVersion 22
    buildToolsVersion '22.0.0'

    defaultConfig {
        applicationId "com.example"
        minSdkVersion 11
        targetSdkVersion 22
    }

    buildTypes {
        release {
            minifyEnabled false
//            proguardFiles getDefaultProguardFile('proguard-android.txt')
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
}
dependencies {

    compile files('libs/gson-1.7.1.jar')
    compile files('libs/universal-image-loader-1.9.1.jar')

    compile files('libs/libGoogleAnalyticsServices.jar')
    compile 'com.android.support:appcompat-v7:22.2.0'
    compile 'com.android.support:recyclerview-v7:22.0.+'
    compile files('libs/volley.jar')

    compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.2'
}

我不确定,罪魁祸首可能是我的 gradle 文件或较低版本中的依赖项。

谁能告诉我我做错了什么? 我错过了什么吗

我发现了很多类似的帖子问题,但不幸的是,仍然没有答案。

使用 volley lib,而不是 HttpClient 为我工作。

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.UUID;

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.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;


/**
 * Created by mobileappz113 on 17/11/16.
 */
public class OkHttpUrlStack extends HurlStack {

    private static final int CONNECT_TIMEOUT_MILLIS = 60 * 1000; // 30s
    private static final int READ_TIMEOUT_MILLIS = 85 * 1000; // 45s
    // private final OkUrlFactory okUrlFactory;

    public OkHttpUrlStack(Context mContext) {
        //this(new OkHttpClient(), mContext);
    }




    @Override
    protected HttpsURLConnection createConnection(URL url) throws IOException {
        HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url.openConnection();
        try {
            httpsURLConnection.setSSLSocketFactory(getSSLSocketFactory());
            httpsURLConnection.setHostnameVerifier(getHostnameVerifier());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return httpsURLConnection;
    }

   /* static Cache getCache(Context mContext) {
        return new Cache(getCacheDir(mContext), 1024);
    }*/

    public static File getCacheDir(Context mContext) {
        File outputDir = mContext.getCacheDir(); // context being the Activity pointer
        File outputFile = null;
        try {
            outputFile = File.createTempFile(UUID.randomUUID().toString(), "tmp", outputDir);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return outputFile;

    }

    public static HostnameVerifier getHostnameVerifier() {
        return new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                //return true; // verify always returns true, which could cause insecure network traffic due to trusting TLS/SSL server certificates for wrong hostnames
                HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
//                return hv.verify("localhost", session);
                return true;
            }
        };
    }

    public static javax.net.ssl.SSLSocketFactory getSSLSocketFactory()
            throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException, KeyManagementException {
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        InputStream caInput = App.getContext().getResources().openRawResource(R.raw.dummy_certificate); // this cert file stored in \app\src\main\res\raw folder path

        Certificate ca = cf.generateCertificate(caInput);
        caInput.close();

        KeyStore keyStore = KeyStore.getInstance("BKS");
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);

        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);

        TrustManager[] wrappedTrustManagers = getWrappedTrustManagers(tmf.getTrustManagers());

        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, wrappedTrustManagers, null);

        return sslContext.getSocketFactory();
    }

    public static TrustManager[] getWrappedTrustManagers(TrustManager[] trustManagers) {
        final X509TrustManager originalTrustManager = (X509TrustManager) trustManagers[0];
        return new TrustManager[]{
                new X509TrustManager() {
                    public X509Certificate[] getAcceptedIssuers() {
                        return originalTrustManager.getAcceptedIssuers();
                    }

                    public void checkClientTrusted(X509Certificate[] certs, String authType) {
                        try {
                            if (certs != null && certs.length > 0) {
                                certs[0].checkValidity();
                            } else {
                                originalTrustManager.checkClientTrusted(certs, authType);
                            }
                        } catch (CertificateException e) {
                            Log.w("checkClientTrusted", e.toString());
                        }
                    }

                    public void checkServerTrusted(X509Certificate[] certs, String authType) {
                        try {
                            if (certs != null && certs.length > 0) {
                                certs[0].checkValidity();
                            } else {
                                originalTrustManager.checkServerTrusted(certs, authType);
                            }
                        } catch (CertificateException e) {
                            Log.w("checkServerTrusted", e.toString());
                        }
                    }
                }
        };
    }
}

并称它为 -

public RequestQueue getRequestQueue() {
        if (mRequestQueue == null) {
            OkHttpUrlStack okHttpUrlStack = new OkHttpUrlStack(getApplicationContext());
            mRequestQueue = Volley.newRequestQueue(getApplicationContext(), okHttpUrlStack);
        }

        return mRequestQueue;
    }