我试图连接到一个运行godaddy 256bit SSL证书的IIS6盒子,我得到了错误:

java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

我一直在想是什么原因导致的,但目前还没有头绪。

以下是我的联系方式:

HttpsURLConnection conn;              
conn = (HttpsURLConnection) (new URL(mURL)).openConnection();
conn.setConnectTimeout(20000);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.connect();
String tempString = toString(conn.getInputStream());

当前回答

回复一个很旧的帖子。但也许它会帮助一些新手,如果以上都行不通的话。

解释:我知道没人想听废话解释;而是解决方案。但是在一行代码中,您试图从本地计算机访问服务到不信任您的计算机的远程计算机。您的请求需要获得远程服务器的信任。

解决方案:下面的解决方案假设您满足以下条件

试图从本地机器访问远程api。 你正在为Android应用开发 您的远程服务器在代理过滤下(您在浏览器设置中使用代理来访问远程api服务,通常是登台或开发服务器) 你是在真实的设备上测试

步骤:

你需要一个.keystore扩展文件来注册你的应用。如果你不知道如何创建.keystore文件;然后按照以下小节创建.keystore文件,否则跳转到下一小节签署Apk文件

创建.keystore文件

打开Android Studio。单击顶部菜单Build > Generate Signed APK。在下一个窗口中单击Create new…按钮。在新窗口中,请在所有字段中输入数据。记住我建议的两个密码字段应该有相同的密码;不要使用不同的密码;并且记住最上面字段的保存路径键存储路径:。输入所有字段后单击OK按钮。

签署Apk文件

现在需要使用刚才创建的.keystore文件构建一个签名应用程序。遵循以下步骤

Build > Clean Project, wait till it finish cleaning Build > Generate Signed APK Click Choose existing... button Select the .keystore file we just created in the Create .keystore file section Enter the same password you created while creating in Create .keystore file section. Use same password for Key store password and Key password fields. Also enter the alias Click Next button In the next screen; which might be different based on your settings in build.gradle files, you need to select Build Types and Flavors. For the Build Types choose release from the dropdown For Flavors however it will depends on your settings in build.gradle file. Choose staging from this field. I used the following settings in the build.gradle, you can use the same as mine, but make sure you change the applicationId to your package name productFlavors { staging { applicationId "com.yourapplication.package" manifestPlaceholders = [icon: "@drawable/ic_launcher"] buildConfigField "boolean", "CATALYST_DEBUG", "true" buildConfigField "boolean", "ALLOW_INVALID_CERTIFICATE", "true" } production { buildConfigField "boolean", "CATALYST_DEBUG", "false" buildConfigField "boolean", "ALLOW_INVALID_CERTIFICATE", "false" } } Click the bottom two Signature Versions checkboxes and click Finish button.

几乎有:

所有艰苦的工作都完成了,现在是真理的运动。为了访问通过代理备份的登台服务器,您需要在您的实际测试Android设备中进行一些设置。

Android设备的代理设置:

点击Android手机内的设置,然后点击wi-fi 长按已连接的wifi,选择“修改网络” 如果看不到代理主机名字段,则单击高级选项 在代理主机名中输入要连接的主机IP或名称。典型的登台服务器将命名为stg.api.mygoodcompany.com 端口输入四位数端口号,例如9502 点击保存按钮

最后一站:

记住,我们在签名apk文件部分生成了签名apk文件。现在是时候安装APK文件了。

打开终端,更改为已签名的apk文件夹 将你的Android设备连接到你的机器 从Android设备中删除之前安装的apk文件 执行adb安装apk文件的名称 如果由于某种原因,上述命令返回adb命令没有找到。填写完整路径为:C:\Users\shah\AppData\Local\Android\sdk\platform-tools\adb.exe安装apk文件的名称

我希望问题能得到解决。如果没有,请给我留言。

萨拉姆!

其他回答

我得到的错误消息与此类似,但原因是自签名证书已经过期。 当尝试openssl客户端时,它给了我一个原因,当我在firefox中检查证书对话框时忽略了这个原因。

因此,通常情况下,如果证书在密钥存储库中并且它是“VALID”,则此错误将消失。

与公认的答案相反,您不需要自定义信任管理器,您需要修复您的服务器配置!

我在连接Apache服务器时遇到了同样的问题,该服务器错误地安装了dynadot/alphassl证书。我正在使用HttpsUrlConnection (Java/Android)连接,这是抛出-

javax.net.ssl.SSLHandshakeException: 
  java.security.cert.CertPathValidatorException: 
    Trust anchor for certification path not found.

实际的问题是服务器配置错误——用http://www.digicert.com/help/或类似工具测试,它甚至会告诉你解决方案:

证书不是由受信任的权威机构签署的(根据Mozilla的根存储进行检查)。如果您从受信任的权威机构购买了证书,则可能只需要安装一个或多个中间证书。请与您的证书提供商联系,以便在您的服务器平台上执行此操作。”

您也可以在openssl中查看证书:

Openssl s_client -debug -connect www.thedomaintocheck.com:443

你可能会看到:

验证返回码:21(无法验证第一个证书)

在前面的输出中:

depth=0 OU = Domain Control Validated, CN = www.thedomaintocheck.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 OU = Domain Control Validated, CN = www.thedomaintocheck.com
verify error:num=27:certificate not trusted
verify return:1
depth=0 OU = Domain Control Validated, CN = www.thedomaintocheck.com
verify error:num=21:unable to verify the first certificate`

证书链将只包含1个元素(您的证书):

Certificate chain
 0 s:/OU=Domain Control Validated/CN=www.thedomaintocheck.com
  i:/O=AlphaSSL/CN=AlphaSSL CA - G2

... 但是应该引用链中的签名授权,回到Android信任的授权(Verisign, GlobalSign等):

Certificate chain
 0 s:/OU=Domain Control Validated/CN=www.thedomaintocheck.com
   i:/O=AlphaSSL/CN=AlphaSSL CA - G2
 1 s:/O=AlphaSSL/CN=AlphaSSL CA - G2
   i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
 2 s:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
   i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA

配置服务器的说明(和中间证书)通常由颁发证书的机构提供,例如:http://www.alphassl.com/support/install-root-certificate.html

在安装了我的证书颁发者提供的中间证书之后,我现在在使用HttpsUrlConnection连接时没有错误。

在姜饼手机,我总是得到这个错误:信任锚没有找到Android SSL连接,即使我设置依赖于我的证书。

下面是我使用的代码(在Scala语言中):

object Security {
    private def createCtxSsl(ctx: Context) = {
        val cer = {
            val is = ctx.getAssets.open("mycertificate.crt")
            try
                CertificateFactory.getInstance("X.509").generateCertificate(is)
            finally
                is.close()
        }
        val key = KeyStore.getInstance(KeyStore.getDefaultType)
        key.load(null, null)
        key.setCertificateEntry("ca", cer)

        val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm)
    tmf.init(key)

        val c = SSLContext.getInstance("TLS")
        c.init(null, tmf.getTrustManagers, null)
        c
    }

    def prepare(url: HttpURLConnection)(implicit ctx: Context) {
        url match {
            case https: HttpsURLConnection ⇒
                val cSsl = ctxSsl match {
                    case None ⇒
                        val res = createCtxSsl(ctx)
                        ctxSsl = Some(res)
                        res
                    case Some(c) ⇒ c
                }
                https.setSSLSocketFactory(cSsl.getSocketFactory)
            case _ ⇒
        }
    }

    def noSecurity(url: HttpURLConnection) {
        url match {
            case https: HttpsURLConnection ⇒
                https.setHostnameVerifier(new HostnameVerifier {
                    override def verify(hostname: String, session: SSLSession) = true
                })
            case _ ⇒
        }
    }
}

下面是连接代码:

def connect(securize: HttpURLConnection ⇒ Unit) {
    val conn = url.openConnection().asInstanceOf[HttpURLConnection]
    securize(conn)
    conn.connect();
    ....
}

try {
    connect(Security.prepare)
} catch {
    case ex: SSLHandshakeException /*if ex.getMessage != null && ex.getMessage.contains("Trust anchor for certification path not found")*/ ⇒
        connect(Security.noSecurity)
}

基本上,我在自定义证书上设置了信任。如果失败,我就禁用安全机制。这不是最好的选择,但这是我所知道的对于老旧和有问题的手机的唯一选择。

这个示例代码,可以很容易地翻译成Java。

您可以在运行时信任特定的证书。 只需从服务器下载,放入资产,然后使用ssl-utils-android像这样加载:

OkHttpClient client = new OkHttpClient();
SSLContext sslContext = SslUtils.getSslContextForCertificateFile(context, "BPClass2RootCA-sha2.cer");
client.setSslSocketFactory(sslContext.getSocketFactory());

在上面的例子中,我使用了OkHttpClient,但是SSLContext可以用于Java中的任何客户端。

如果你有任何问题,请提出来。我是这个小图书馆的作者。

根据最新的Android文档(2017年3月)更新:

当你得到这种类型的错误:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
        at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:374)
        at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:209)
        at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:478)
        at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:433)
        at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)
        at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)
        at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:282)
        at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177)
        at libcore.net.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:271)

问题可能是以下情况之一:

颁发服务器证书的CA未知 服务器证书不是由CA签署的,而是自签署的 服务器配置缺少一个中间CA

解决方案是教会HttpsURLConnection信任一组特定的ca。怎么做?请查看https://developer.android.com/training/articles/security-ssl.html#CommonProblems

其他使用com.loopj的AsyncHTTPClient的人。android:android-async-http库,请检查设置AsyncHttpClient使用HTTPS。