嗨我正在測試Android連接與證書。 我在我的ubuntu桌面上創建了一個默認的ssl服務器。啓用ssl並創建默認的自簽名證書。然後,我用firefox連接到https://localhost
,向異常添加證書,然後使用Firefox將cerificate保存爲.pem文件。 我在我的android projetc中添加了certificate.pem在res/raw中Android Https連接自簽名證書:hostName未驗證
我已經從android開發者網站獲得了這段代碼,通過https連接我的證書(我不想相信我只想驗證的證書在原始文件夾中使用證書是正確的)。
所以,當我連接,我得到: 了java.lang.RuntimeException:java.io.IOException的:主機名「192.168.1.111」未經過驗證
這裏是我用來驗證證書
類public class VerifyKey extends AsyncTask<Void, Void, Void>{
public static final String CERTIFICATE_TYPE_X_509 = "X.509";
public static final String CERTIFICATE_ALIAS = "user_desktop";
public static final String SERVER_URL = "https://192.168.1.111";
@Override
protected Void doInBackground(Void... params) {
// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
CertificateFactory cf = null;
InputStream certificateInputStream = getApplicationContext().getResources().openRawResource(R.raw.user_desktop);
Certificate certificate = null;
try {
cf = CertificateFactory.getInstance(CERTIFICATE_TYPE_X_509);
certificate = cf.generateCertificate(certificateInputStream);
Log.d(TAG, "Certificate : " + certificate.toString());
Log.d(TAG, "Certificate public key : " + certificate.getPublicKey());
} catch (CertificateException e) {
throw new RuntimeException(e);
} finally {
if (certificateInputStream != null) {
try {
certificateInputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = null;
try {
keyStore = KeyStore.getInstance(keyStoreType);
if (keyStore != null) {
keyStore.load(null, null);
keyStore.setCertificateEntry(CERTIFICATE_ALIAS, certificate);
} else {
throw new RuntimeException("KeyStore is null");
}
} catch (KeyStoreException e) {
throw new RuntimeException(e);
} catch (CertificateException e) {
throw new RuntimeException(e);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = null;
try {
tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
if (tmf != null) {
tmf.init(keyStore);
} else {
throw new RuntimeException("TrustManagerFactory is null");
}
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (KeyStoreException e) {
throw new RuntimeException(e);
}
// Create an SSLContext that uses our TrustManager
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("TLS");
TrustManager[] trustManagers = tmf.getTrustManagers();
sslContext.init(null, trustManagers, null);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (KeyManagementException e) {
throw new RuntimeException(e);
}
// Tell the URLConnection to use a SocketFactory from our SSLContext
URL url = null;
HttpsURLConnection httpsURLConnection =
null;
InputStream in = null;
try {
url = new URL(SERVER_URL);
Log.d(TAG, "URL : "+url.toString());
httpsURLConnection = (HttpsURLConnection)url.openConnection();
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
Log.d(TAG, "Socket factory : "+socketFactory.toString());
httpsURLConnection.setSSLSocketFactory(socketFactory);
in = httpsURLConnection.getInputStream(); //IOException exception gets triggered here
Toast.makeText(getApplicationContext(), in.toString(), Toast.LENGTH_SHORT).show();
} catch (MalformedURLException e) {
throw new RuntimeException(e);
} catch (SSLHandshakeException e){
throw new RuntimeException(e);
} catch(UnknownHostException e){
throw new RuntimeException(e);
} catch (ConnectException e1){
throw new RuntimeException(e1);
} catch (IOException e) {
throw new RuntimeException(e);
}
return null;
}
}
我從http://developer.android.com/training/articles/security-ssl.html#SelfSigned
得到這個代碼,我得到這個錯誤對三星Galaxy S4搭載Android 4.3
我對HTTPS沒有太多的經驗,所以在這裏我想實現的是使用應用程序驗證服務器證書的證書。 請如果有人可以建議我可以在代碼中修改。
我也有一個疑問,因爲我的服務器是一個.local服務器,但我使用IP連接,目標是能夠連接使用兩個IP主機名,這將是問題時,找到主機名? 感謝很多提前
編輯:我添加代碼來獲取主機名:
InetAddress addr = InetAddress.getByName(SERVER_URL);
String hostName = addr.getHostName();
我一直在使用主機名而不是IP嘗試,但我仍然得到同樣的異常:
Caused by: java.io.IOException: Hostname '<user.hostname.com>' was not verified
at libcore.net.http.HttpConnection.verifySecureSocketHostname(HttpConnection.java:223)
at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:446)
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)
在windows中是什麼解決方案? – CoronaPintu
對不起,我不使用窗口,所以不知道,你應該創建一個新的職位,因爲你的問題可能完全不同於我的。另外要注意的是,在Android中,有時候IP地址被「拒絕」,所以你應該提供你自己的主機名稱驗證器 – vallllll