当前位置: 首页 > 面试题库 >

Android java.security.cert.CertPathValidatorException:找不到证书路径的信任锚

丌官瀚
2023-03-14
问题内容

android应用有三台主机进行身份验证和授权。最终主机是REST API。首次使用Oauth身份验证和授权过程,它可以正常工作。

但是,如果 用户 在登录并访问REST API提供的服务后 杀死了该应用程序 ,然后再次打开该应用程序,则会出现此问题。
在这段时间内,身份验证和授权过程不会发生,只有REST API会发生。
这是造成原因,java.security.cert.CertPathValidatorException
但在首次使用(登录然后使用该应用程序)期间正在工作。

有人可以解释此异常背后的情况以及该应用程序有什么问题。如果根据此SO答案将认证异常忽略如下,则此方法有效。

SSLSocketFactory sslSocketFactory = null;

        try {
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(
                    TrustManagerFactory.getDefaultAlgorithm());
            // Initialise the TMF as you normally would, for example:
            try {
                tmf.init((KeyStore)null);
            } catch(KeyStoreException e) {
                e.printStackTrace();
            }
            TrustManager[] trustManagers = tmf.getTrustManagers();

            final X509TrustManager origTrustmanager = (X509TrustManager)trustManagers[0];

            // Create a trust manager that does not validate certificate chains
            TrustManager[] wrappedTrustManagers = new TrustManager[]{
                    new X509TrustManager() {
                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            return origTrustmanager.getAcceptedIssuers();
                        }

                        public void checkClientTrusted(X509Certificate[] certs, String authType) {
                            try {
                                origTrustmanager.checkClientTrusted(certs, authType);
                            } catch(CertificateException e) {
                                e.printStackTrace();
                            }
                        }

                        public void checkServerTrusted(X509Certificate[] certs, String authType) {
                            try {
                                origTrustmanager.checkServerTrusted(certs, authType);
                            } catch(CertificateException e) {
                                e.printStackTrace();
                            }
                        }
                    }
            };
            //TrustManager[] trustAllCerts = TrustManagerFactory.getInstance("SSL").getTrustManagers();

            // Install the all-trusting trust manager
            final SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, wrappedTrustManagers, new java.security.SecureRandom());
            // Create an ssl socket factory with our all-trusting manager
            sslSocketFactory = sslContext.getSocketFactory();
        } catch (NoSuchAlgorithmException | KeyManagementException e) {
            e.printStackTrace();
        }
        return sslSocketFactory;

我对http请求使用Okhttp 3。任何建议都将有助于解决问题。并且请告诉我是否使用上述代码段,是否违反安全规定?对应用程序的安全性有影响吗?


问题答案:

我正在回答这个问题,以便根据android开发人员站点给出有关方案和解决方案的想法,以使他人受益。我已经使用自定义信任管理器解决了这个问题。

问题出在服务器证书上,它缺少中间证书颁发机构。但是,第一个流证书路径以某种方式完成,结果是成功进行了证书路径验证。

android开发人员网站中对此有解决方案。建议使用信任此服务器证书的自定义信任管理器,或者建议服务器在服务器链中包括中间CA。

自定义信任管理器。来源:https : //developer.android.com/training/articles/security-
ssl.html#UnknownCa

// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// From https://www.washington.edu/itconnect/security/ca/load-der.crt
InputStream caInput = new BufferedInputStream(new FileInputStream("load-der.crt"));
Certificate ca;
try {
    ca = cf.generateCertificate(caInput);
    System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
    caInput.close();
}

// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);

// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);

// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
// Tell the okhttp to use a SocketFactory from our SSLContext
OkHttpClient okHttpClient client = new OkHttpClient.Builder().sslSocketFactory(context.getSocketFactory()).build();

更新:
从服务器端将中间证书颁发机构添加到证书链后,我的问题得到解决。这是最好的解决方案,将证书与应用程序捆绑在一起需要在证书到期或与证书管理相关的任何其他问题时更新应用程序。

更新:03/09/2017 加载证书文件的最简单方法是使用原始资源。

InputStream caInput = new BufferedInputStream(context
                .getResources().openRawResource(R.raw.certfilename));

其中certfilename是放置在resources /
raw文件夹中的证书文件。还不sslSocketFactory(SSLSocketFactory sslSocketFactory)建议使用okhttp ,建议使用okhttp api文档中的建议方法。

另外,从服务器获取证书时,最好使用openssl。

openssl s_client -connect {server-address}:{port} -showcerts

因为我以前是从firefox那里抢来的,并且遇到了病毒防护人员更改了它的情况。



 类似资料:
  • 我正在Android上开发一个客户端应用程序,它连接到我的服务器,它在负载均衡器后面的AWS上,我在GoDaddy上创建了一个SSL证书,并将其添加到负载均衡器上。 浏览器上的一切都很顺利,它可以识别证书,但是当我试图用Android调用API时,我遇到了一个例外: 我找到了一些讨论谁说在app上添加证书,但是在证书服务器端是不是就没有办法修复了呢?这不是证书的问题吗?

  • 我遇到了Android4设备的一个问题,它在连接到服务器时收到以下异常: 但出于某种原因,我不明白它在Android4版本中开始失败了。 我尝试了信任所有证书的解决方案[LINK],它起作用了,但这显然存在安全问题,比如将您的应用程序暴露于“中间人”攻击 如何实现具有默认行为但仅将服务器的证书白名单的TrustManager。 在证书链给了我两个证书的格式: 用获得的url和证书替换了示例中的ur

  • 问题内容: 我正在尝试建立与HTTPS站点的连接,并且我GOT打印例外:。 我的原始代码如下: 然后,我在这里阅读了Google的文章,并将代码修改为: 关于文件,我使用此站点来检查该站点的证书。我发现了3个证书,我不知道该使用哪个证书。我一一尝试。 一个名称“ VeriSign 3类公共主要证书颁发机构-G5”导致以下例外: 当我使用一个名称为“ VeriSign Class 3 Secure

  • 问题内容: 在我的服务器(生产服务器)中,我具有goDaddy ssl证书。我有iOS和Android应用程序都与服务器连接,iOS都没有问题连接,Android版本为4. 一切都很好,但是设备版本为2.3。我总是收到SSLHandshakeException。 我在Android开发人员页面(https://developer.android.com/training/articles/secu

  • 我正在创建一个android应用程序,它使用与服务器通信。我使用和发出请求。这些适用于标准请求。以下是我遵循的步骤。 步骤1:使用命令从服务器获取证书文件 步骤2:使用以下命令将证书转换为BKS格式 它要求我输入密码,文件成功创建。 第三步: 创建一个OkHttpClient,并使用它来发出https请求 第四步: 必须创建RestAdapter 但最后,当运行该应用程序时,它向我抛出。请帮我解决

  • 我有一个通过SSL从node.js提供服务的网站。当我使用web浏览器(桌面和Android)访问站点时。一切都很好--当我检查证书是有效的并且一切看起来都很好时,锁出现了,表明站点是安全的。这应该意味着服务器设置正确,对吧? 然而,当我尝试使用Android WebView对完全相同的站点时,页面无法加载--我甚至在日志中看不到对该网页的请求。安德烈,在放松logcat上的过滤器后,我注意到了这