我试图连接到一个运行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());
根据最新的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。
在姜饼手机,我总是得到这个错误:信任锚没有找到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。
我使用这些方法,其中一个是上述解决方案对我有效:
第一:
public okhttp3.OkHttpClient getUnsafeOkHttpClient() {
try {
// Create a trust manager that does not validate
certificate chains
final TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
@Override
public void
checkClientTrusted(java.security.cert.X509Certificate[] chain,
String authType) throws CertificateException {
}
@Override
public void
checkServerTrusted(java.security.cert.X509Certificate[] chain,
String authType) throws CertificateException {
}
@Override
public java.security.cert.X509Certificate[]
getAcceptedIssuers() {
return new
java.security.cert.X509Certificate[]{};
}
}
};
// Install the all-trusting trust manager
final SSLContext sslContext =
SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new
java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting
manager
final SSLSocketFactory sslSocketFactory =
sslContext.getSocketFactory();
okhttp3.OkHttpClient.Builder builder = new
okhttp3.OkHttpClient.Builder();
builder.sslSocketFactory(sslSocketFactory,
(X509TrustManager)trustAllCerts[0]);
builder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession
session) {
return true;
}
});
okhttp3.OkHttpClient okHttpClient = builder.build();
return okHttpClient;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
第二:
@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("SSL");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection
.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new
HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
});
} catch (Exception ignored) {
}
}
和:
把这些库放到你的类路径中:
implementation 'com.squareup.okhttp:okhttp:2.3.0'
implementation 'com.squareup.okhttp:okhttp-urlconnection:2.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-
core:3.3.0'
一定要在课堂上给他们打电话