带 HTTPS 的 KSOAP 2 Android

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3440062/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 10:12:34  来源:igfitidea点击:

KSOAP 2 Android with HTTPS

androidsoaphttpsksoap2

提问by rallat

I am using KSOAP2 to manage SOAP in Android but it use https for the SOAP url and I am getting this error: javax.net.ssl.SSLException: Not trusted server certificate
A normal error because the certificate is untrusted, but anyone knows how to workaround with this error? I can not manage the certificate because is from a other company and I don't have access to change it.

我正在使用 KSOAP2 来管理 Android 中的 SOAP,但它使用 https 作为 SOAP url 并且我收到此错误:javax.net.ssl.SSLException:不可信服务器证书
一个正常错误,因为证书不受信任,但任何人都知道如何解决此错误的方法?我无法管理证书,因为它来自其他公司,我无权更改它。

Thanks

谢谢

采纳答案by zirael

I can't comment yet so i post my comments to rallat answer here. His solution works but it needs further explanations. To run ksoap2 with ssl:

我还不能发表评论,所以我在这里发表我的评论给 rallat 答案。他的解决方案有效,但需要进一步解释。使用 ssl 运行 ksoap2:

  1. Put ksoap2-android-assembly-2.5.2-jar-with-dependencies.jarin a project
  2. Download ksoap2 sources from https://github.com/mosabua/ksoap2-android/tree/(ksoap2 repository)
  3. Copy HttpTransportSE.java, ServiceConnectionSE.java(I also needed to copy Transport.java, ServiceConnection.javaand HeaderProperty.java). Delete imports from those files and make sure that they use your files (not imports from ksoap2.jar)
  4. Use rallat answer ( I copy-pasted it):

    • ServiceConnectionSE.javaadd this for accept untrusted certificate:

      private TrustManager[] trustAllCerts = new TrustManager[] {
          new X509TrustManager() {
              public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                  return null;
              }
              public void checkClientTrusted(
                  java.security.cert.X509Certificate[] certs, String authType) {
              }
              public void checkServerTrusted(
                  java.security.cert.X509Certificate[] certs, String authType) {
              }
          }
      };
      
    • then use this constructors to allow untrusted certificates and not verified hostnames:

      public ServiceConnectionSE(String url) throws IOException {
          try {
              SSLContext sc = SSLContext.getInstance("TLS");
              sc.init(null, trustAllCerts, new java.security.SecureRandom());
              HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
          } catch (Exception e) {
              e.getMessage();
          }
          connection = (HttpsURLConnection) new URL(url).openConnection();
          ((HttpsURLConnection) connection).setHostnameVerifier(new AllowAllHostnameVerifier());
      }    
      
    • Second contructor

      public ServiceConnectionSE(Proxy proxy, String url) throws IOException {
          try {
              SSLContext sc = SSLContext.getInstance("TLS");
              sc.init(null, trustAllCerts, new java.security.SecureRandom());
              HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
           } catch (Exception e) {
              e.getMessage();
           }
           connection = (HttpsURLConnection) new URL(url).openConnection();
          ((HttpsURLConnection) connection).setHostnameVerifier(new AllowAllHostnameVerifier());
      
          connection.setUseCaches(false);
          connection.setDoOutput(true);
          connection.setDoInput(true);
      }
      
  5. In your code just use:

    HttpTransportSE aht = new HttpTransportSE(URL);    
    aht.call(SOAP_ACTION, envelope);
    
  1. 放入ksoap2-android-assembly-2.5.2-jar-with-dependencies.jar一个项目
  2. https://github.com/mosabua/ksoap2-android/tree/(ksoap2存储库)下载 ksoap2 源代码
  3. 复制HttpTransportSE.java, ServiceConnectionSE.java(我还需要复制Transport.java,ServiceConnection.javaHeaderProperty.java)。从这些文件中删除导入并确保它们使用您的文件(而不是从 导入ksoap2.jar
  4. 使用 rallat 答案(我复制粘贴了它):

    • ServiceConnectionSE.java添加此以接受不受信任的证书:

      private TrustManager[] trustAllCerts = new TrustManager[] {
          new X509TrustManager() {
              public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                  return null;
              }
              public void checkClientTrusted(
                  java.security.cert.X509Certificate[] certs, String authType) {
              }
              public void checkServerTrusted(
                  java.security.cert.X509Certificate[] certs, String authType) {
              }
          }
      };
      
    • 然后使用这个构造函数来允许不受信任的证书和未经验证的主机名:

      public ServiceConnectionSE(String url) throws IOException {
          try {
              SSLContext sc = SSLContext.getInstance("TLS");
              sc.init(null, trustAllCerts, new java.security.SecureRandom());
              HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
          } catch (Exception e) {
              e.getMessage();
          }
          connection = (HttpsURLConnection) new URL(url).openConnection();
          ((HttpsURLConnection) connection).setHostnameVerifier(new AllowAllHostnameVerifier());
      }    
      
    • 第二建设者

      public ServiceConnectionSE(Proxy proxy, String url) throws IOException {
          try {
              SSLContext sc = SSLContext.getInstance("TLS");
              sc.init(null, trustAllCerts, new java.security.SecureRandom());
              HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
           } catch (Exception e) {
              e.getMessage();
           }
           connection = (HttpsURLConnection) new URL(url).openConnection();
          ((HttpsURLConnection) connection).setHostnameVerifier(new AllowAllHostnameVerifier());
      
          connection.setUseCaches(false);
          connection.setDoOutput(true);
          connection.setDoInput(true);
      }
      
  5. 在您的代码中只需使用:

    HttpTransportSE aht = new HttpTransportSE(URL);    
    aht.call(SOAP_ACTION, envelope);
    

Other things as in tutorials

教程中的其他内容

回答by Neonigma

Checking again this problem, I've discovered a more clean solution for me. No KSOAP2 files modification needed.

再次检查这个问题,我发现了一个更干净的解决方案。无需修改 KSOAP2 文件。

In your project, link the ksoap2-android-assembly-3.0.0-jar, with no modifications.

在您的项目中,链接ksoap2-android-assembly-3.0.0-jar,无需修改。

Next, create a file named SSLConnection.javawith this code:

接下来,创建一个SSLConnection.java使用以下代码命名的文件:

package com.example.mypackage;

import android.util.Log;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class SSLConection {

    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 X509Certificate[] getAcceptedIssuers() {
            return (_AcceptedIssuers);
        }
    }

    public static void allowAllSSL() {

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

        javax.net.ssl.SSLContext context;

        if (trustManagers == null) {
            trustManagers = new TrustManager[]{new _FakeX509TrustManager()};
        }

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

And just call to SSLConection.allowAllSSL();before calling a server method via KSOAP2. It's all, works for me. All SSL certificates are accepted and I can use KSOAP2 with https protocol.

只需SSLConection.allowAllSSL();在通过 KSOAP2 调用服务器方法之前调用 。这一切,对我有用。接受所有 SSL 证书,我可以将 KSOAP2 与 https 协议一起使用。

回答by jowett

Create a new class FakeX509TrustManager to handle the certificate problem,

创建一个新类 FakeX509TrustManager 来处理证书问题,

    FakeX509TrustManager.allowAllSSL();
    HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);

The new created class is as the following:

新创建的类如下:

public class FakeX509TrustManager implements X509TrustManager { 

    private static TrustManager[] trustManagers; 
    private static final X509Certificate[] _AcceptedIssuers = new 
X509Certificate[] {}; 

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

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

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

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

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

    public static void allowAllSSL() { 
            HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() 
{ 
                    @Override 
                    public boolean verify(String hostname, 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 (NoSuchAlgorithmException e) { 
                    e.printStackTrace(); 
            } catch (KeyManagementException e) { 
                    e.printStackTrace(); 
            } 

       HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory()); 
    } 

} 

回答by rallat

I find the answer by myself

我自己找答案

  • on ServiceConnectionSE.java add this for accept untrusted certificate:

    private TrustManager[] trustAllCerts = new TrustManager[]{
        new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
            public void checkClientTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
            }
            public void checkServerTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
            }
        }
    };
    
  • then in the constructor add this to allow untrusted certificates and not verified hostnames:

        try {
           SSLContext sc = SSLContext.getInstance("TLS");
           sc.init(null, trustAllCerts, new java.security.SecureRandom());
           HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        } catch (Exception e) {
           e.getMessage();
        }
        connection = (HttpsURLConnection) new URL(url).openConnection();
        ((HttpsURLConnection) connection).setHostnameVerifier(new AllowAllHostnameVerifier());
    
  • 在 ServiceConnectionSE.java 上添加此以接受不受信任的证书:

    private TrustManager[] trustAllCerts = new TrustManager[]{
        new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
            public void checkClientTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
            }
            public void checkServerTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
            }
        }
    };
    
  • 然后在构造函数中添加它以允许不受信任的证书和未验证的主机名:

        try {
           SSLContext sc = SSLContext.getInstance("TLS");
           sc.init(null, trustAllCerts, new java.security.SecureRandom());
           HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        } catch (Exception e) {
           e.getMessage();
        }
        connection = (HttpsURLConnection) new URL(url).openConnection();
        ((HttpsURLConnection) connection).setHostnameVerifier(new AllowAllHostnameVerifier());