Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android |谷歌地图api密钥和自签名证书冲突_Java_Android_Google Maps_Ssl - Fatal编程技术网

Java Android |谷歌地图api密钥和自签名证书冲突

Java Android |谷歌地图api密钥和自签名证书冲突,java,android,google-maps,ssl,Java,Android,Google Maps,Ssl,在浪费了很多时间之后,我发现我的google maps api密钥与我的自签名ssl证书冲突 这是我信任证书的方法 public static void trustSelfSignedSSL() { try { HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { public boolean verify(String hostnam

在浪费了很多时间之后,我发现我的google maps api密钥与我的自签名ssl证书冲突

这是我信任证书的方法

public static void trustSelfSignedSSL() {

        try {
            HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
                public boolean verify(String hostname, SSLSession session) {
                    return hostname.equals(Config.HTTPS_CERTIFICATE_URL);
                    //System.out.println("*************################### " + hostname);
                    //return true;
                }
            });

            CertificateFactory cf = CertificateFactory.getInstance("X.509");

            Context appContext = HBGApplication.context;
            AssetManager assets = appContext.getAssets();
            InputStream caInput = assets.open(Config.HTTPS_CERTIFICATE_ASSETS_FILE);
            Certificate ca;
            try {
                ca = cf.generateCertificate(caInput);
                System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
            } finally {
                caInput.close();
            }

            String keyStoreType = KeyStore.getDefaultType();
            KeyStore keyStore = KeyStore.getInstance(keyStoreType);
            keyStore.load(null, null);
            keyStore.setCertificateEntry("ca", ca);


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

            SSLContext context = SSLContext.getInstance("TLS");
            context.init(null, tmf.getTrustManagers(), null);
            HttpsURLConnection.setDefaultSSLSocketFactory(
                    context.getSocketFactory());
        } catch (Exception e) { // should never happen
            e.printStackTrace();
        }
    } 
如果我对此进行注释,则此方法将正确工作。 我曾尝试在verify方法中验证google maps端点,但它似乎从未在maps的此方法中输入


所以我的问题是:除了地图服务之外,我如何使用我的自签名证书进行服务通信?

我发现了一个受此链接启发的解决方案


它建议添加带有TrustManager的自定义SslSocketFactory好的,我找到了解决方案:

protected static Certificate ca;

/**
     * set self signed certificate to trust
     */
    public static void trustSelfSignedSSL() {

        try {
            // set hostname verifier to check hostname validity
            HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
                public boolean verify(String hostname, SSLSession session) {
                    return hostname.equals(Config.HTTPS_CERTIFICATE_URL) || hostname.equals(Config.HTTPS_GOOGLE_URL);
                }
            });

            // load certificate
            hbgCa = getCert();

            // add certificate to key store
            if (null != hbgCa) {
                String keyStoreType = KeyStore.getDefaultType();
                KeyStore keyStore = KeyStore.getInstance(keyStoreType);
                keyStore.load(null, null);
                keyStore.setCertificateEntry("hbgCa", hbgCa);

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

                SSLContext context = SSLContext.getInstance("TLS");
                context.init(null, tmf.getTrustManagers(), null);
//          HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
                HttpsURLConnection.setDefaultSSLSocketFactory(createSslSocketFactory());
            }
        } catch (Exception e) { // should never happen
            e.printStackTrace();
        }
    }


    /**
     * create a custom sslsocketfactory to trust server connections
     *
     * @return
     * @throws Exception
     */
    private static SSLSocketFactory createSslSocketFactory() throws Exception {
        TrustManager[] byPassTrustManagers = new TrustManager[]{new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }

            public void checkClientTrusted(X509Certificate[] chain, String authType) {
            }

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

                // Loading the CA cert
                if (null == ca) {
                    ca = getCert();
                }

                for (X509Certificate cert : chain) {

                    // check if the certificate is the selfsigned trusted one
                    if (verifiyCertificate(ca, cert)) {
                        return;
                    }
                    // check if current certificate belongs to google
                    if (cert.getIssuerX500Principal().getName().equals("CN=Google Internet Authority G2,O=Google Inc,C=US")) {
                        return;
                    }
                }

        // if none certificate trusted throw certificate exception to tell to not trust connection
                throw new CertificateException();
            }
        }
        };

        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, byPassTrustManagers, new SecureRandom());
        return sslContext.getSocketFactory();
    }


    /**
     * verifiy a certificate against the other
     */
    private static boolean verifiyCertificate(Certificate cert1, Certificate cert2) {
        try {
            cert1.verify(cert2.getPublicKey());
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * load and return selfsigned local cert
     *
     * @return
     */
    private static Certificate getCert() {

        try {
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            Context appContext = HBGApplication.getWrapperContext();
            AssetManager assets = appContext.getAssets();
            InputStream caInput = assets.open(Config.HTTPS_CERTIFICATE_ASSETS_FILE);
            Certificate ca;

            try {
                return cf.generateCertificate(caInput);
            } catch (CertificateException e) {
                e.printStackTrace();
            } finally {
                caInput.close();
            }

            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
为了避免默认的SSLSocketFactory,我们有机会实现自定义TrustManager。 因为我正在开发客户端,所以我的应用程序应该在checkServerTrusted方法中检查服务器标识。 在这种方法中,我们获取证书,并尝试根据服务器收到的所有证书链对其进行验证。 如果验证失败,将抛出一个异常,因此我们可以手动抛出一个CertificateException,指示证书未被接受。 起初,我下载了谷歌证书并将其添加到证书队列中,但当他的有效期到期时,我的应用程序将不再工作。所以我决定检查证书的发行人X500主体的名称是否和谷歌的名称匹配

现在我可以连接到我的服务器,我可以使用谷歌服务。 我试着用另一个证书更改证书以进行测试,但是连接不再可信,所以我认为它工作得很好


如果有人能向我建议一些错误,我们将非常感谢

显然,在这之后,验证HostnameVerifier的验证方法中的google主机名是一件好事,应该是这样的,而这个链接可能会回答这个问题,最好在这里包括答案的基本部分,并提供链接供参考。如果链接页面发生更改,仅链接的答案可能无效。-好的,我正在制定正确的解决方案,如果可行,我会发布:)