这是我信任证书的方法
public static void trustSelfSignedSSL() {
try {
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return hostname.equals(Config.HTTPS_CERTIFICATE_URL);
//System.out.println("*************################### " + hostname);
//return true;
}
});
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Context appContext = HBGApplication.context;
AssetManager assets = appContext.getAssets();
InputStream caInput = assets.open(Config.HTTPS_CERTIFICATE_ASSETS_FILE);
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
HttpsURLConnection.setDefaultSSLSocketFactory(
context.getSocketFactory());
} catch (Exception e) { // should never happen
e.printStackTrace();
}
}
如果我评论此方法地图可以正常工作。 我已经尝试在验证方法中验证google maps端点,但似乎它从未在此方法中输入地图。
所以我的问题是:如何将自签名证书用于除地图服务之外的服务通信?
答案 0 :(得分:0)
我找到了受此链接启发的解决方案
它建议使用TrustManager
添加自定义SslSocketFactory答案 1 :(得分:0)
好的,我找到了解决方案:
protected static Certificate ca;
/**
* set self signed certificate to trust
*/
public static void trustSelfSignedSSL() {
try {
// set hostname verifier to check hostname validity
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return hostname.equals(Config.HTTPS_CERTIFICATE_URL) || hostname.equals(Config.HTTPS_GOOGLE_URL);
}
});
// load certificate
hbgCa = getCert();
// add certificate to key store
if (null != hbgCa) {
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("hbgCa", hbgCa);
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
// HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
HttpsURLConnection.setDefaultSSLSocketFactory(createSslSocketFactory());
}
} catch (Exception e) { // should never happen
e.printStackTrace();
}
}
/**
* create a custom sslsocketfactory to trust server connections
*
* @return
* @throws Exception
*/
private static SSLSocketFactory createSslSocketFactory() throws Exception {
TrustManager[] byPassTrustManagers = new TrustManager[]{new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
// Loading the CA cert
if (null == ca) {
ca = getCert();
}
for (X509Certificate cert : chain) {
// check if the certificate is the selfsigned trusted one
if (verifiyCertificate(ca, cert)) {
return;
}
// check if current certificate belongs to google
if (cert.getIssuerX500Principal().getName().equals("CN=Google Internet Authority G2,O=Google Inc,C=US")) {
return;
}
}
// if none certificate trusted throw certificate exception to tell to not trust connection
throw new CertificateException();
}
}
};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, byPassTrustManagers, new SecureRandom());
return sslContext.getSocketFactory();
}
/**
* verifiy a certificate against the other
*/
private static boolean verifiyCertificate(Certificate cert1, Certificate cert2) {
try {
cert1.verify(cert2.getPublicKey());
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* load and return selfsigned local cert
*
* @return
*/
private static Certificate getCert() {
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Context appContext = HBGApplication.getWrapperContext();
AssetManager assets = appContext.getAssets();
InputStream caInput = assets.open(Config.HTTPS_CERTIFICATE_ASSETS_FILE);
Certificate ca;
try {
return cf.generateCertificate(caInput);
} catch (CertificateException e) {
e.printStackTrace();
} finally {
caInput.close();
}
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
为了避免默认的SSLSocketFactory,我们有机会实现自定义的TrustManager。 因为我正在开发客户端,我的应用程序应该检查服务器身份到checkServerTrusted方法。 在这种方法中,我们获得了我们的证书,并且我们尝试针对服务器所有收到的证书链进行验证。 如果验证失败,则抛出异常,因此我们可以手动抛出表示不接受证书的CertificateException。 最初我已下载谷歌证书并将其添加到证书队列,但当他的有效期到期时,我的应用程序将不再有效。所以我决定检查证书的IssuerX500Principal的名称是否与谷歌的名称匹配。
现在我可以连接到我的服务器了,我可以使用谷歌服务。 我已经尝试用另一个更改证书用于测试目的,并且连接不再受信任,所以我认为它运行良好。
如果有人可以向我推荐一些错误,我们将非常感激