2011-01-10 19 views
6

私はksoap2-androidを使用してSSL経由でwcfサービスを呼び出しています。私はそれがSSLなしで動作するようにすることができますが、今はSSL経由で電話をかけたいのですが、私はいくつかの問題に取り組んできました。ksoap2-androidを使用した信頼できない証明書

は私の代わりにHttpTransportSEのHttpsTransportSEを使用していますが、私はエラーを取得しています: javax.net.ssl.SSLException:信頼されていないサーバ証明書私はこの問題を解決するにはどうすればよい

を?

問題を解決するために、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に記載されているように偽のトラストマネージャをインストールしてから、ksoap2へのSSL通信/呼び出しを行う前にallowAllSSL()を呼び出すことができます。新しいデフォルトのHostnameVerifierとTrustManagerが登録されます。 ksoap2は、SSL通信を行うときにデフォルトのものを使用し、魅力的に機能します。

また、アプリケーションのローカルトラストマネージャに証明書をインストールすることもできます。私は安全なネットワークにいて、中間者攻撃を恐れていないので、最初にやっただけです。

これは、new KeepAliveHttpsTransportSE(host, port, file, timeout);のようにKeepAliveHttpsTransportSEを使用する必要があることがわかりました。パラメータはURLオブジェクトに格納されます。 Jiraのインストールにアクセスするには、new KeepAliveHttpsTransportSE("host.whatever", 443, "/rpc/soap/jirasoapservice-v2", 1000)のようなものです。

エミュレータやデバイス上ではなくJ2SE環境で、J2SE/MEのksoap2ライブラリで再生するのに使いたいテクノロジやWebサービスを使い慣れていない方が便利な場合があります(KeepAlive)HttpsTransportSEのものがありません(ksoap2-j2se-full-2.1.2.jarを使用しました)。あなたは、Androidスピンオフksoap2-androidからHttpsTransportSE、KeepAliveHttpsTransportSE、およびHttpsServiceConnectionSEの3つのクラスのソースを取得し、それらをJ2SEプロジェクトに入れて使用することができます。それは私にとってはうまくいっていて、未知で非常に複雑なWebサービスでは、最初のステップを正しく行うための生産性の向上になりました。

+0

あなたの最初のソリューションを使用することは多少なりともno sslを使用することと同じです – Rafa

0

はい、おそらくあなたが

Https Connection Android

これを試してみることができますまあ、そこにあるこの

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. Serverは、サーバーのURLです。
  2. 443はデフォルトのhttpsポートですが、コンストラクタが期待するのでポートを指定する必要があります。
  3. URL WS操作
  4. 1000年へのパスのように構築されたタイムアウト

ES: を[https://でサーバー:443/URL]

+0

ありがとうございました。このリンクは私をもっと助けました... – akk

+0

ありがとう!これは完全に動作します! – lomza

1

作品私のために KSOAP + WebサービスWCF with 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 { 

     } 
    } 
関連する問題