【问题标题】:Unsafe implementation of the interface X509TrustManager - Google PlayX509TrustManager 接口的不安全实现 - Google Play
【发布时间】:2021-01-27 12:48:27
【问题描述】:

当我尝试将应用程序上传到 google play 时,我收到一条消息。 “接口 x509trustmanager 的不安全实现”。在来自 Google Play 的消息中,它说:

为避免验证 SSL 证书时出现问题,请更改代码 X509TrustManager 接口中的 checkServerTrusted 方法,所以 时抛出 CertificateException 或 IllegalArgumentException 它会检测到可疑证书。

我发现的所有选项都使用 checkValidity 方法来验证证书,但 Google 也添加了:

不要使用 checkValidity 来验证服务器的证书。这 方法检查证书的有效性,而不是其安全性。

如何正确更改 checkServerTrusted 方法的代码?我当前的 x509TrustManager 实现:

X509TrustManager trustManager = new X509TrustManager() {
        @Override
        public X509Certificate[] getAcceptedIssuers() {
            X509Certificate[] cArrr = new X509Certificate[0];
            return cArrr;
        }

        @Override
        public void checkServerTrusted(final X509Certificate[] chain,
                                       final String authType) throws CertificateException {
            try {
                chain[0].checkValidity();
            } catch (Exception e) {
                throw new CertificateException("Certificate not valid or trusted.");
            }
        }

        @Override
        public void checkClientTrusted(final X509Certificate[] chain,
                                       final String authType) throws CertificateException {
        }
    };

【问题讨论】:

  • 完全删除它的实现。除非您有自签名证书,否则无需使用上述代码块。

标签: java android google-play android-security trustmanager


【解决方案1】:

我以这种方式更改了 X509TrustManager 实现,应用通过了 Google Play 验证:

TrustManager[] victimizedManager = new TrustManager[]{

                new X509TrustManager() {

                    public X509Certificate[] getAcceptedIssuers() {

                        X509Certificate[] myTrustedAnchors = new X509Certificate[0];

                        return myTrustedAnchors;
                    }

                    @Override
                    public void checkClientTrusted(X509Certificate[] certs, String authType) {
                    }

                    @Override
                    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                        if(chain == null || chain.length == 0)throw new IllegalArgumentException("Certificate is null or empty");
                        if(authType == null || authType.length() == 0) throw new IllegalArgumentException("Authtype is null or empty");
                        if(!authType.equalsIgnoreCase("ECDHE_RSA") &&
                                !authType.equalsIgnoreCase("ECDHE_ECDSA") &&
                                !authType.equalsIgnoreCase("RSA") &&
                                !authType.equalsIgnoreCase("ECDSA")) throw new CertificateException("Certificate is not trust");
                        try {
                            chain[0].checkValidity();
                        } catch (Exception e) {
                            throw new CertificateException("Certificate is not valid or trusted");
                        }
                    }
                }
        };

【讨论】:

    【解决方案2】:

    我以前遇到过这个错误。就我而言,这就是修复它的原因:

    private boolean isVerified;
    
    @SuppressLint("TrulyRandom")
    public static void handleSSLHandshake() {
        try {
            TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }
    
                @Override
                public void checkClientTrusted(X509Certificate[] certs, String authType) {
                }
    
                @Override
                public void checkServerTrusted(X509Certificate[] certs, String authType) {
                }
            }};
    
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCerts, new SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(final String host, final SSLSession session) {
                    System.out.print("host" + host+ "\n");
                    isVerified = host.equalsIgnoreCase(Constants.hostNameVerifierString)
                            || host.contains("google") || host.contains("gstatic");
    
                    System.out.print(isVerified);
                    return isVerified;
                }
            });
        } catch (Exception ignored) {
        }
    }
    

    在您有网络调用的活动中,您可以调用handleSSLHandshake() 方法。或者,如果你使用 Dagger 或任何依赖注入库,你应该能够在任何你想创建网络调用的地方注入它。

    Constants.hostNameVerifierString 是我用于网络调用的 URL,添加了“google”和“gstatic”是因为我也在使用 google 地图。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-02
      相关资源
      最近更新 更多