11

当我访问 wsdl url 时,我在 android 中遇到异常

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

我已经使用ksoap2库来执行该WSDL文件。

我也实施了认证课程,但我遇到了同样的问题

请告诉是否有任何解决方案。

我正在使用这两个类进行认证:

AndroidInsecureHttpsServiceConnectionSE 类:

    package com.example.androidwsdltest;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import org.ksoap2.HeaderProperty;
import org.ksoap2.transport.ServiceConnection;

import android.util.Log;

public class AndroidInsecureHttpsServiceConnectionSE implements
        ServiceConnection {
    private HttpsURLConnection connection;

    public AndroidInsecureHttpsServiceConnectionSE(String host, int port,
            String file, int timeout) throws IOException {
        // allowAllSSL();
        connection = (HttpsURLConnection) new URL("https", host, port, file)
                .openConnection();
        updateConnectionParameters(timeout);
    }

    private static TrustManager[] trustManagers;

    public static class EasyX509TrustManager implements X509TrustManager {

        private X509TrustManager standardTrustManager = null;

        /**
         * Constructor for EasyX509TrustManager.
         */
        public EasyX509TrustManager(KeyStore keystore)
                throws NoSuchAlgorithmException, KeyStoreException {
            super();
            TrustManagerFactory factory = TrustManagerFactory
                    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
            factory.init(keystore);
            TrustManager[] trustmanagers = factory.getTrustManagers();
            if (trustmanagers.length == 0) {
                throw new NoSuchAlgorithmException("no trust manager found");
            }
            this.standardTrustManager = (X509TrustManager) trustmanagers[0];
        }

        /**
         * @see 
         *      javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate
         *      [],String authType)
         */
        public void checkClientTrusted(X509Certificate[] certificates,
                String authType) throws CertificateException {
            standardTrustManager.checkClientTrusted(certificates, authType);
        }

        /**
         * @see 
         *      javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate
         *      [],String authType)
         */
        public void checkServerTrusted(X509Certificate[] certificates,
                String authType) throws CertificateException {
            if ((certificates != null) && (certificates.length == 1)) {
                certificates[0].checkValidity();
            } else {
                standardTrustManager.checkServerTrusted(certificates, authType);
            }
        }

        /**
         * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
         */
        public X509Certificate[] getAcceptedIssuers() {
            return this.standardTrustManager.getAcceptedIssuers();
        }

    }

    public static class FakeX509TrustManager implements 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);
        }
    }

    /**
     * Allow all SSL certificates by setting up a host name verifier that passes
     * everything and as well setting up a SocketFactory with the
     * #FakeX509TrustManager.
     */
    public static void allowAllSSL() {

        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {

            @Override
            public boolean verify(String hostname, SSLSession session) {
                // TODO Auto-generated method stub
                return true;
            }

        });

        SSLContext context = null;

        if (trustManagers == null) {
            try {
                trustManagers = new TrustManager[] { new EasyX509TrustManager(
                        null) };
            } catch (NoSuchAlgorithmException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (KeyStoreException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        try {
            context = 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());
        }
        // HttpsURLConnection.setDefaultAllowUserInteraction(true);
        HttpsURLConnection.setDefaultSSLSocketFactory(context
                .getSocketFactory());
    }

    /**
     * update the connection with the timeout parameter as well as allowing SSL
     * if the Android version is 7 or lower (since these versions have a broken
     * certificate manager, which throws a SSL exception saying "Not trusted
     * security certificate"
     * 
     * @param timeout
     */
    private void updateConnectionParameters(int timeout) {
        connection.setConnectTimeout(timeout); // 20 seconds
        connection.setReadTimeout(timeout); // even if we connect fine we want
                                            // to time out if we cant read
                                            // anything..
        connection.setUseCaches(false);
        connection.setDoOutput(true);
        connection.setDoInput(true);

        allowAllSSL();

        /*
         * int buildVersion = Build.VERSION.SDK_INT; if (buildVersion <= 7) {
         * Log.d("Detected old operating system version " + buildVersion +
         * " with SSL certificate problems. Allowing " + "all certificates.",
         * String.valueOf(buildVersion)); allowAllSSL(); } else {
         * Log.d("Full SSL active on new operating system version ",
         * String.valueOf(buildVersion)); }
         */
    }

    public void connect() throws IOException {
        connection.connect();
    }

    public void disconnect() {
        connection.disconnect();
    }

    public List getResponseProperties() {
        Map properties = connection.getHeaderFields();
        Set keys = properties.keySet();
        List retList = new LinkedList();

        for (Iterator i = keys.iterator(); i.hasNext();) {
            String key = (String) i.next();
            List values = (List) properties.get(key);

            for (int j = 0; j < values.size(); j++) {
                retList.add(new HeaderProperty(key, (String) values.get(j)));
            }
        }

        return retList;
    }

    public void setRequestProperty(String key, String value) {
        // We want to ignore any setting of "Connection: close" because
        // it is buggy with Android SSL.
        if ("Connection".equalsIgnoreCase(key)
                && "close".equalsIgnoreCase(value)) {
            // do nothing
        } else {
            connection.setRequestProperty(key, value);
        }
    }

    public void setRequestMethod(String requestMethod) throws IOException {
        connection.setRequestMethod(requestMethod);
    }

    public OutputStream openOutputStream() throws IOException {
        return connection.getOutputStream();
    }

    public InputStream openInputStream() throws IOException {
        return connection.getInputStream();
    }

    public InputStream getErrorStream() {
        return connection.getErrorStream();
    }

    public String getHost() {
        return connection.getURL().getHost();
    }

    public int getPort() {
        return connection.getURL().getPort();
    }

    public String getPath() {
        return connection.getURL().getPath();
    }

}

AndroidInsecureKeepAliveHttpsTransportSE 类:

 package com.example.androidwsdltest;

import java.io.IOException;

import org.ksoap2.transport.HttpsTransportSE;
import org.ksoap2.transport.ServiceConnection;

public class AndroidInsecureKeepAliveHttpsTransportSE extends HttpsTransportSE {

    private AndroidInsecureHttpsServiceConnectionSE conn = null;
    private final String host;
    private final int port;
    private final String file;
    private final int timeout;

    public AndroidInsecureKeepAliveHttpsTransportSE(String host, int port,
            String file, int timeout) {
        super(host, port, file, timeout);
        this.host = host;
        this.port = port;
        this.file = file;
        this.timeout = timeout;
    }

    @Override
    protected ServiceConnection getServiceConnection() throws IOException {
        super.getServiceConnection();
        conn = new AndroidInsecureHttpsServiceConnectionSE(host, port, file,
                timeout);
        conn.setRequestProperty("Connection", "keep-alive");

        return conn;
    }
}

使用这些认证课程后,我得到了同样的例外

请帮我..

提前致谢......:)

4

2 回答 2

2

你应该有一个授权的 SSL 证书 - 这可能会解决问题,这是解决问题的最佳方法。

如果没有,你必须做一点工作:

这个概念是,当使用 SSL 时,Android 比平时更难,你应该在你的 android 上拥有证书权限,因此,你应该在你的 Android 上拥有一个基本的密钥库(如谷歌商店,但免费,并且在您自己的 Android),并通过一些基本操作使您自己的 Android 受信任。

  1. 在服务器上找到您的证书,并使用私钥导出(您应具有管理员权限)。这可以通过从 start->run + certmgr.msc 运行来完成。查找“受信任的根证书颁发机构”。找到您的证书并进行导出(keytool 可以加载现有的 pfx 证书。在 *.cer 类型的证书上,可能会有小问题。
  2. 你应该有一个钥匙工具。您可以在http://keytool.sourceforge.net/上找到说明 您可以安装,但我更喜欢以下建议:这是通过帮助 - 软件更新 - 查找并安装 - 搜索新功能来完成的...。单击新建远程站点并在名称和 URL 中添加http://keytool.sourceforge.net/update,并确保已选中。点击完成。
  3. 添加一个新的密钥库,并加载您的证书(使用 pcs12 协议,选择您能记住的密码)。
  4. 需要添加的代码如下:http: //developer.android.com/training/articles/security-ssl.html#UnknownCa
  5. 你应该把你的联系联系起来。您可以像示例一样使用 HttpTransportSE::ServiceConnection::setSSLSocketFactory。 https://code.google.com/p/androidzon/source/browse/Androidzon/src/it/marco/ksoap2/HttpTransportSE.java?r=77 (只需创建自己的新功能,并将其连接到网络服务。如果不起作用,请删除 ?wsdl)

祝你好运!!!

于 2014-01-29T09:29:54.987 回答
1

该错误是由于与服务器建立信任时出现的问题。大多数情况下,您的信任库没有服务器提交的证书。以下2个问题的答案可能会对您有所帮助。

[1] -如何通过 Android 访问 SSL 连接?

[2] -证书受 PC 信任,但不受 Android 信任

于 2013-04-03T05:22:23.127 回答