2015-10-11 114 views
4

在我的Android應用程序中,我需要使用OkHttp庫執行一些請求到我的服務器。 我有一個由四個部分組成一個SSL證書:OkHttp信任證書

  • AddTrustExternalCARoot.crt
  • COMODORSAAddTrustCA.crt
  • COMODORSADomainValidationSecureServerCA.crt
  • www_mydomain_com.crt

我已經進口的所有零件在portecle 1.9中,然後我設置密鑰庫密碼並導出了.bks證書。

然後我將這個mycert.bks插入到我的應用程序項目的res/raw文件夾中。 現在我嘗試連接到我的服務器通過HTTPS使用此代碼:

OkHttpClient client = new OkHttpClient(); 
     try{ 
      client.setSslSocketFactory(getPinnedCertSslSocketFactory(context)); 
      RequestBody formBody = new FormEncodingBuilder() 
        .add("params", "xxx") 
        .build(); 
      Request request = new Request.Builder() 
        .url("https:\\mydomain.com") 
        .post(formBody) 
        .build(); 

      Response response = client.newCall(request).execute(); 
      if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); 
      return response.body().string();; 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     return null; 

    } 


private SSLSocketFactory getPinnedCertSslSocketFactory(Context context) { 
    try { 
     KeyStore trusted = KeyStore.getInstance("BKS"); 
     InputStream in = context.getResources().openRawResource(R.raw.mycert); 
     trusted.load(in, "mypass".toCharArray()); 
     SSLContext sslContext = SSLContext.getInstance("TLS"); 
     TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
     TrustManagerFactory.getDefaultAlgorithm()); 
     trustManagerFactory.init(trusted); 
     sslContext.init(null, trustManagerFactory.getTrustManagers(), null); 
     return sslContext.getSocketFactory(); 
    } catch (Exception e) { 
     Log.e("MyApp", e.getMessage(), e); 
    } 
    return null; 
} 

但我得到一個例外,這是logcat的:

10-11 18:22:51.930 13604-5341/com.aaa.android.client W/System.err: javax.net.ssl.SSLPeerUnverifiedException: Hostname myserver.net not verified: 
10-11 18:22:51.930 13604-5341/com.aaa.android.client W/System.err:  certificate: sha1/"mysha1string" 
10-11 18:22:51.930 13604-5341/com.aaa.android.client W/System.err:  DN: CN=www.aaa.it,OU=PositiveSSL,OU=Domain Control Validated 
10-11 18:22:51.930 13604-5341/com.aaa.android.client W/System.err:  subjectAltNames: [www.aaa.it, aaa.it] 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.squareup.okhttp.Connection.connectTls(Connection.java:244) 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.squareup.okhttp.Connection.connectSocket(Connection.java:199) 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.squareup.okhttp.Connection.connect(Connection.java:172) 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:367) 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.squareup.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:128) 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:328) 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:245) 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.squareup.okhttp.Call.getResponse(Call.java:267) 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:224) 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:195) 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.squareup.okhttp.Call.execute(Call.java:79) 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.aaa.android.client.Login$BackgroundTask.doInBackground(Login.java:294) 
10-11 18:22:51.940 13604-5341/com.aaa.android.client W/System.err:  at com.aaa.android.client.Login$BackgroundTask.doInBackground(Login.java:277) 
10-11 18:22:51.950 13604-5341/com.aaa.android.client W/System.err:  at android.os.AsyncTask$2.call(AsyncTask.java:288) 
10-11 18:22:51.950 13604-5341/com.aaa.android.client W/System.err:  at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
10-11 18:22:51.950 13604-5341/com.aaa.android.client W/System.err:  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 
10-11 18:22:51.950 13604-5341/com.aaa.android.client W/System.err:  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
10-11 18:22:51.950 13604-5341/com.aaa.android.client W/System.err:  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
10-11 18:22:51.950 13604-5341/com.aaa.android.client W/System.err:  at java.lang.Thread.run(Thread.java:818) 

問題出在哪裏?

UPDATE: 我已經做了很多的嘗試在這個圖書館,我發現了這一點:

  • 如果我做的HTTPS請求:自動\ link.com OkHttp庫 信任所有證書。
  • 如果我只想信任我的證書,我必須做我上面發佈的解決方案 。
  • 如果我不想接受所有主機,但不使用我的證書,我可以使用hostnameVerifier作爲BNK建議。

但是,爲什麼我發佈的問題,如果我的解決方案的作品?因爲我很笨,而且我對vps網址(vpsxxx.net/directory.php)做了請求,而不是我的網域(mydomain.it/directory.php)。

很明顯,SSL證書應用於我的域名而不是我的vps。

我希望這可以對某人有用。

P.S .:對不起,我的英語! :D

回答

3

讓我們假設您的服務器應用程序託管在服務器機器中,該服務器機器具有服務器證書,其中"Issued to""localhost",例如。然後,在verify方法裏面,你可以驗證"localhost"

HostnameVerifier hostnameVerifier = new HostnameVerifier() { 
    @Override 
    public boolean verify(String hostname, SSLSession session) { 
     HostnameVerifier hv = 
      HttpsURLConnection.getDefaultHostnameVerifier(); 
     return hv.verify("localhost", session); 
    } 
}; 

您可以通過以下鏈接閱讀更多:

  1. HostnameVerifier

    這是一個握手過程中使用,如果URL的主機名不匹配對等的標識主機。

  2. Common Problems with Hostname Verification

    原因之一可能發生這種情況是由於服務器配置錯誤。該 服務器配置不具備與你 嘗試訪問的服務器,一個主題 或主題備用名稱字段的證書......

然後,您可以使用主機名驗證在您的應用程序中,請撥打client.setHostnameVerifier(hostnameVerifier);。希望這可以幫助!

P/S:另一個臨時的解決方法是return true;verify方法,然而,這是不推薦使用。

+0

閱讀我的更新!非常感謝! – diegocom