2013-11-28 101 views
1

嗨我正在測試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) 

回答

0

我設法解決了這個問題,實際上是證書有問題:

sudo a2enmod ssl 
sudo rm -rf /etc/apache2/ssl 
sudo mkdir /etc/apache2/ssl 
sudo openssl req -new -x509 -days 365 -nodes -out /etc/apache2/ssl/apache.pem -keyout /etc/apache2/ssl/apache.key 

它改變權限複製/etc/apache2/ssl/apache.pem別的地方,爲777(???) ,然後添加新apache.pem到RES /應用程序的原始文件夾

那麼常見我已經把我的服務器的FQDN如host.name.com名稱字段,然後,我更新了cerificate和在/ etc鍵設置/ Apache2的/網站可用/默認的SSL

這一切都歸功於網站https://library.linode.com/web-servers/apache/ssl-guides/ubuntu-10.04-lucid

+0

在windows中是什麼解決方案? – CoronaPintu

+0

對不起,我不使用窗口,所以不知道,你應該創建一個新的職位,因爲你的問題可能完全不同於我的。另外要注意的是,在Android中,有時候IP地址被「拒絕」,所以你應該提供你自己的主機名稱驗證器 – vallllll