2015-06-15 213 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