2011-01-10 4 views
6

Я использую ksoap2-android для вызова службы wcf через SSL. Я могу заставить его работать без SSL, но теперь я хочу сделать вызов через SSL, но я столкнулся с некоторыми проблемами.Не доверенный сертификат с использованием ksoap2-android

Я использую HttpsTransportSE вместо HttpTransportSE, но я получаю сообщение об ошибке: javax.net.ssl.SSLException: Не доверенный сертификат

Как я могу исправить этот сервер?

Могу ли я добавить сертификат сервера в Keystore на Android, чтобы решить эту проблему?

private static final String SOAP_ACTION = "http://example.com/Service/GetInformation"; 
private static final String METHOD_NAME = "GetInformation"; 
private static final String NAMESPACE = "http://example.com";  
private static final String URL = "dev.example.com/Service.svc"; 

public static Result GetInformation() 
{ 
    SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME); 

    PropertyInfo property = new PropertyInfo(); 
    property.name = "request"; 

    Request request = 
     new Request("12", "13", "Ben"); 

    userInformationProperty.setValue(request); 
    userInformationProperty.setType(request.getClass()); 
    request.addProperty(property); 

    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); 
    envelope.dotNet = true; 
    envelope.setOutputSoapObject(request); 
    envelope.addMapping(NAMESPACE, "Request",new Request().getClass()); 

    HttpsTransportSE transport = new HttpsTransportSE(URL, 443, "", 1000); 

    //HttpTransportSE androidHttpTransport = new HttpTransportSE(URL); 
    transport.debug = true; 

    try 
    { 
     transport.call(SOAP_ACTION, envelope);   
     return Result.FromSoapResponse((SoapObject)envelope.getResponse()); 
    } 
    catch (IOException e) 
    { 
     e.printStackTrace(); 
    } 
    catch (XmlPullParserException e) 
    { 
     e.printStackTrace(); 
    } 

    return null; 
} 

ответ

4

Ну, есть более простой способ сделать это вместо изменения HttpsServiceConnectionSE. Вы можете установить поддельный менеджер доверия, как описано в http://groups.google.com/group/android-developers/browse_thread/thread/1ac2b851e07269ba/c7275f3b28ad8bbc?lnk=gst&q=certificate, а затем вызвать allowAllSSL(), прежде чем выполнять любую связь/вызов SSL с помощью ksoap2. Он зарегистрирует новый HostnameVerifier по умолчанию и TrustManager. ksoap2, когда он делает свою связь по SSL, будет использовать по умолчанию, и он работает как шарм.

Вы также можете приложить еще несколько усилий к этому, сделать его гораздо безопаснее и установить сертификаты в локальном менеджере доверия приложения, я думаю. Я был в безопасной сети и не боялся нападений «человек-в-середине», поэтому я только что сделал первый.

Я счел необходимым использовать KeepAliveHttpsTransportSE следующим образом: new KeepAliveHttpsTransportSE(host, port, file, timeout);. Параметры попадают в объект URL, например, для доступа к установке Jira это что-то вроде new KeepAliveHttpsTransportSE("host.whatever", 443, "/rpc/soap/jirasoapservice-v2", 1000).

Иногда это удобно, если вы новичок в технологии или веб-сервисе, который вы любите использовать с ним в среде J2SE, а не в эмуляторе или даже на устройстве, но в библиотеке j2SE/ME ksoap2 Отсутствует материал (KeepAlive) HttpsTransportSE (я использовал ksoap2-j2se-full-2.1.2.jar). Что вы можете сделать, так это получить источники для трех классов HttpsTransportSE, KeepAliveHttpsTransportSE и HttpsServiceConnectionSE из Android-андроида Android-андроида Android и поместить их в свой проект J2SE и использовать их. Это сработало для меня, и это стало улучшением производительности, чтобы получить первые шаги с неизвестным и довольно сложным веб-сервисом.

+0

с использованием вашего первого решения более или менее такое же, как при использовании ssl – Rafa

0

Да, наверное, вы можете попробовать это

Https Connection Android

Там была ошибка, которая была подана на выпуск Tracker относительно этого

http://code.google.com/p/android/issues/detail?id=2388

+0

Что касается первой ссылки: где идет этот код? – Awesome

+0

Вы можете попробовать добавить это, прежде чем делать звонок на сервер – DeRagan

+0

Я предоставил свой текущий код в сообщении. Я просто не вижу, где и как я должен поместить код. – Awesome

11

В дополнение к ответу Vedran с некоторым исходным кодом, извините, я не могу комментировать.

TrustManager:

private static TrustManager[] trustManagers; 

public static class _FakeX509TrustManager implements 
     javax.net.ssl.X509TrustManager { 
    private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[] {}; 

    public void checkClientTrusted(X509Certificate[] arg0, String arg1) 
      throws CertificateException { 
    } 

    public void checkServerTrusted(X509Certificate[] arg0, String arg1) 
      throws CertificateException { 
    } 

    public boolean isClientTrusted(X509Certificate[] chain) { 
     return (true); 
    } 

    public boolean isServerTrusted(X509Certificate[] chain) { 
     return (true); 
    } 

    public X509Certificate[] getAcceptedIssuers() { 
     return (_AcceptedIssuers); 
    } 
} 

public static void allowAllSSL() { 

    javax.net.ssl.HttpsURLConnection 
      .setDefaultHostnameVerifier(new HostnameVerifier() { 
       public boolean verify(String hostname, SSLSession session) { 
        return true; 
       } 
      }); 

    javax.net.ssl.SSLContext context = null; 

    if (trustManagers == null) { 
     trustManagers = new javax.net.ssl.TrustManager[] { new _FakeX509TrustManager() }; 
    } 

    try { 
     context = javax.net.ssl.SSLContext.getInstance("TLS"); 
     context.init(null, trustManagers, new SecureRandom()); 
    } catch (NoSuchAlgorithmException e) { 
     Log.e("allowAllSSL", e.toString()); 
    } catch (KeyManagementException e) { 
     Log.e("allowAllSSL", e.toString()); 
    } 
    javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(context 
      .getSocketFactory()); 
} 

Вызов на свой метод:

allowAllSSL(); 
HttpsTransportSE httpsTransport = new HttpsTransportSE(Server,443, URL, 1000); 

Примечания:

  1. Сервер является URL-адрес сервера.
  2. 443 - это порт https по умолчанию, вам все равно нужно указать порт, поскольку конструктор ожидает его.
  3. URL путь к операции WS
  4. 1000 Э.С. тайм-аут

, который построен как: [https: // сервер: 443/URL]

+0

Большое спасибо. эта ссылка помогла мне больше ... – akk

+0

Спасибо! Это прекрасно работает! – lomza

1

Работы для меня KSOAP + Веб-сервис WCF с eclipse

private static SoapObject getBody(final SoapSerializationEnvelope soapEnvelope) throws Exception { 
     if (soapEnvelope.bodyIn == null) { 
      throw new Exception("soapEnvelope.bodyIn=null"); 
     } 
     else if (soapEnvelope.bodyIn.getClass() == SoapFault.class) { 
      throw new ExceptionLogic((SoapFault) soapEnvelope.bodyIn)); 
     } 
     else { 
      return (SoapObject) soapEnvelope.bodyIn; 
     } 

    } 

private static SoapSerializationEnvelope sendRequete(final SoapObject soapReq, final String classMappingName, 
      final Class<?> classMapping, final int timeOutSpecial) { 



     final SoapSerializationEnvelope soapEnvelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); 
     soapEnvelope.implicitTypes = true; 
     soapEnvelope.dotNet = true; 

     if (classMappingName != null) { 
      soapEnvelope.addMapping(NAMESPACE, classMappingName, classMapping); 
     } 

     soapEnvelope.setOutputSoapObject(soapReq); 

     try { 

      final HttpTransportSE httpTransport = new HttpTransportSE(Constante.urlWebService, timeOutSpecial); 
      httpTransport.debug = BuildConfig.DEBUG; 

      // Prod 
      if (Constante.urlWebService.startsWith("https://")) { 
       final List<HeaderProperty> headerList = new ArrayList<HeaderProperty>(); 
       headerList.add(new HeaderProperty("Authorization", "Basic " 
         + org.kobjects.base64.Base64.encode((Constante.CERTIFICAT_LOGIN + ":" + Constante.CERTIFICAT_MDP).getBytes()))); 

       FakeX509TrustManager.allowAllSSL(); 
       httpTransport.call(NAMESPACE + "/" + soapReq.getName(), soapEnvelope, headerList); 
      } 
      // Test 
      else { 
       httpTransport.call(NAMESPACE + "/" + soapReq.getName(), soapEnvelope); 
      } 

      return soapEnvelope; 
     } 
     catch (final Exception e) { 
      throw new Exception("Erreur : " + e.getMessage(), e); 
     } 

    } 



    private static class FakeX509TrustManager implements X509TrustManager { 
     private static TrustManager[] trustManagers; 
     private final X509Certificate[] _AcceptedIssuers = new X509Certificate[] {}; 

     @Override 
     public X509Certificate[] getAcceptedIssuers() { 
      return _AcceptedIssuers; 
     } 

     public static void allowAllSSL() { 
      HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { 

       @Override 
       public boolean verify(final String hostname, final SSLSession session) { 
        return true; 
       } 
      }); 
      SSLContext context = null; 
      if (trustManagers == null) { 
       trustManagers = new TrustManager[] { new FakeX509TrustManager() }; 
      } 
      try { 
       context = SSLContext.getInstance("TLS"); 
       context.init(null, trustManagers, new SecureRandom()); 
      } 
      catch (final NoSuchAlgorithmException e) { 
       e.printStackTrace(); 
      } 
      catch (final KeyManagementException e) { 
       e.printStackTrace(); 
      } 
      HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory()); 
     } 

     @Override 
     public void checkClientTrusted(final X509Certificate[] arg0, final String arg1) throws CertificateException { 

     } 

     @Override 
     public void checkServerTrusted(final X509Certificate[] chain, final String authType) throws CertificateException { 

     } 
    } 
Смежные вопросы