我目前正在开发一款Android应用(Android Studio 2.0),它将通过HTTPS(使用javax.net.ssl.HttpsURLConnection)连接到我的服务器(Glassfish 4.1,Netbeans 8.1)。目前这一切都在我的本地网络(智能手机+笔记本电脑)上运行。我现在遇到的问题是:
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
我认为因为我的Android应用程序还不信任服务器。我该如何去做它确实信任服务器?
在某些官方文档(http://developer.android.com/training/articles/security-ssl.html)和其他指南中,我看到过提到Keystores或使用.crt文件。但是我在哪里可以获得其中任何一个,如何在移动设备上获取它们?
目前我的代码如下:
public static HttpsURLConnection setupHttpsConnection(URL url, Context context) {
try {
// Load CAs from an InputStream
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = new BufferedInputStream(context.getAssets().open("localhost.crt"));
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
Log.d(LOG_TAG, "> setupHttpsConnection > ca.getSubjectDN = " + ((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 sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
/*
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
HostnameVerifier hv =
HttpsURLConnection.getDefaultHostnameVerifier();
return hv.verify("192.168.0.121", session);
}
};
*/
// Tell the URLConnection to use a SocketFactory from our SSLContext
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
//urlConnection.setHostnameVerifier(hostnameVerifier);
urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());
return urlConnection;
} catch (Exception e) {
e.printStackTrace();
Log.d(LOG_TAG, e.toString());
return null;
}
}
然后在另一个地方我打电话:
urlConnection = Utility.setupHttpsConnection(url, context);
urlConnection.connect(); // <-- Exception thrown here!