2015-06-15 242 views
1

我試圖建立一個Android設備和Web服務之間的連接使用ssl與客戶端證書(服務器檢查作爲要求客戶端證書),服務器上的證書由CA(go-daddy)簽名我也有一個客戶端證書(* .pfx),我休息this tutorial 附加客戶端證書文件, 我打電話給web服務使用kso​​ap2,我不斷收到錯誤403, ,但從設備(或PC)的Web瀏覽器工作正常(安裝證書後)...... 我對客戶端證書瞭解不多,但在我看來,連接並未以正確的方式使用我的證書。Android客戶端證書403

當我用自簽證書測試時,它一切正常。

任何想法我做錯了什麼? 我ksoap2代碼:

public void GetUser(String user_name, String password, boolean isSchedule, 
     boolean writeTostatistic) throws Exception { 

    Log.d(GlobalUtil.TAG_LOG, "Calling GetUser() web service"); 
    String METHOD_NAME = "GetUser"; 
    globalUtil.user = new User(); 
    User us = new User(); 
    HttpsTransportSE httpTransport = new KeepAliveHttpsTransportSE(host, 
      port, file, timeout); 

    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
      SoapEnvelope.VER12); 
    SoapObject Request = new SoapObject(NAMESPACE, METHOD_NAME); 
    httpTransport.debug = true; 
    envelope.dotNet = true; 
    envelope.headerOut = new Element[1]; 
    envelope.headerOut[0] = elementHeaders; 

    Request.addProperty("user_name", user_name); 
    Request.addProperty("password", password); 
    Request.addProperty("isSchedule", isSchedule); 
    Request.addProperty("writeTostatistic", writeTostatistic); 
    envelope.implicitTypes = true; 
    envelope.setOutputSoapObject(Request); // prepare request 

    envelope.addMapping(NAMESPACE, "User", new User().getClass()); 

    if (useCertificate) { 
     try { 
      ((HttpsServiceConnectionSE) httpTransport 
        .getServiceConnection()) 
        .setSSLSocketFactory(sSLContext); 
     } catch (IOException e) { 

      e.printStackTrace(); 
     } 
    } else 
     allowAllSSL(); 

    List<HeaderProperty> httpHeaders = null; 
    try { 

     httpHeaders = httpTransport.call(SOAP_ACTION + METHOD_NAME, 
       envelope, null); 

     SoapObject response = (SoapObject) envelope.getResponse(); 

     if (response == null) 
      return; 

     us.Id = Integer.parseInt(response.getProperty("Id").toString()); 
     if (!response.getProperty("User_Name").toString() 
       .equals("anyType{}")) 
      us.User_Name = response.getProperty("User_Name").toString(); 
     if (!response.getProperty("Password").toString() 
       .equals("anyType{}")) 
      us.Password = response.getProperty("Password").toString(); 
     if (!response.getProperty("USER_HEBREW_FIRSTNAME").toString() 
       .equals("anyType{}")) 
      us.USER_HEBREW_FIRSTNAME = response.getProperty(
        "USER_HEBREW_FIRSTNAME").toString(); 
     if (!response.getProperty("USER_HEBREW_LASTNAME").toString() 
       .equals("anyType{}")) 
      us.USER_HEBREW_LASTNAME = response.getProperty(
        "USER_HEBREW_LASTNAME").toString(); 

     us.Merhav = Integer.parseInt(response.getProperty("Merhav") 
       .toString()); 
     us.Yaam = Integer.parseInt(response.getProperty("Yaam").toString()); 
     us.Tat_Mifal = Integer.parseInt(response.getProperty("Tat_Mifal") 
       .toString()); 
     us.Ezor = Integer.parseInt(response.getProperty("Ezor").toString()); 
     us.EzorLahatz = Integer.parseInt(response.getProperty("EzorLahatz") 
       .toString()); 
     /* 
     * us.PasswordExpirationDate=(Date) 
     * response.getProperty("PasswordExpirationDate"); 
     */ 
     us.PasswordExpirationDate = User 
       .ParsePasswordExpirationDate((response 
         .getProperty("PasswordExpirationDate").toString())); 
     us.Password = password; 
     globalUtil.user = us; 
     SetSessionCookie(httpHeaders); 
     Log.d(GlobalUtil.TAG_LOG, "Finish calling GetUser() web service"); 

    } catch (IOException | XmlPullParserException e1) { 
     if(e1!=null) 
     { 
      Log.e(GlobalUtil.TAG_LOG, e1.getMessage()); 
      throw e1; 
     } 
     Log.e(GlobalUtil.TAG_LOG, "Error in Login web service."); 
     Log.e(GlobalUtil.TAG_LOG, "requestDump: " 
       + httpTransport.requestDump); 
     Log.e(GlobalUtil.TAG_LOG, "responseDump: " 
       + httpTransport.responseDump); 
    } 

回答

1

這可能是太晚了你,但我在一個類似的情況......

舊版Android(和前1.7的Java)的有問題(缺乏)SSL中的SNI。據說這從2.3開始就已經修復了,但我相信我設法在我的5.0 Android模擬器中模仿了這個bug。 (可能通過使用自定義套接字上下文工廠。)在瀏覽器中,我可以使用來自Android的相同密鑰存儲庫/信任存儲庫訪問URL,我獲得403個。

是什麼讓我相信確實缺乏服務器名稱指示是原因。 ..

openssl s_client -tls1_2 -connect myhost.domain.com:443 -state -cert client.crt -key client.key -pass pass:******** -CAfile server.cer -servername myhost.domain.com 

...最後省略-servername參數導致403,這正是我的Android代碼實現的結果。 :D