java - Android - 由 : java. security.cert.CertPathValidatorException 引起:未找到证书路径的信任 anchor

标签 java android ssl ssl-certificate androidhttpclient

我在测试环境中使用自签名 CA 证书,但在使用 HttpClient 访问 api 时遇到问题.... 请帮我解决这个问题....

W/System.err: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. / W/System.err: at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:333) at com.android.okhttp.internal.http.SocketConnector.connectTls(SocketConnector.java:103) at com.android.okhttp.Connection.connect(Connection.java:167) at com.android.okhttp.Connection.connectAndSetOwner(Connection.java:209) at com.android.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:128) at com.android.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:352) at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:341) at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:259) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:454) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:114) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:245) at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getOutputStream(DelegatingHttpsURLConnection.java:218) at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java) at .Components.HttpClient.getInternetData(HttpClient.java:135) at .Components.HttpClient.doInBackground(HttpClient.java:53) at .Components.HttpClient.doInBackground(HttpClient.java:31) 03-11 20:18:19.305 8156-8238/ W/System.err: at android.os.AsyncTask$2.call(AsyncTask.java:295) at java.util.concurrent.FutureTask.run(FutureTask.java:237) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) at java.lang.Thread.run(Thread.java:818) Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:324) at com.android.org.conscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:225) at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:115) at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:571) at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) 03-11 20:18:19.306 8156-8238/ W/System.err: at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:329) ... 20 more

这是我的调用方法:

HttpClient client = new HttpClient(context, new ReturnProcess(), params_hash_map);
client.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, URL);

基类:

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.widget.Toast;

import org.apache.http.client.ClientProtocolException;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;

public class HttpClient extends AsyncTask<String, String, String>
{
    Context context;
    CallReturn callReturn;
    LinkedHashMap params;

    public HttpClient (Context context, CallReturn callReturn, LinkedHashMap params)
    {
        this.context = context;
        this.callReturn = callReturn;
        this.params = params;
    }

    @Override
    protected String doInBackground(String... url)
    {
        String responseString = null;
        try
        {
            if (isNetworkConnected())
            {

                responseString = getInternetData(url[0], params);
                if (responseString.equalsIgnoreCase("ENDUP") || responseString.equalsIgnoreCase("logout"))
                {
//                    Logs.isLogout = true;
                }
            }
            else
            {
                responseString = "NoInterNet";
            }
        }
        catch (ClientProtocolException e)
        {
            responseString = "ClientProtocolException";
            Utilities.handleException(e);
        }
        catch (IOException e)
        {
            responseString = "IOException";
            Utilities.handleException(e);
        }
        catch (Exception e)
        {
            responseString = "Exception";
            Utilities.handleException(e);
        }
        return responseString;
    }

    @Override
    protected void onPostExecute(String s)
    {
        super.onPostExecute(s);
        callReturn.onCallCompleted(s);
    }

    public boolean isNetworkConnected()
    {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo ni = cm.getActiveNetworkInfo();
        if (ni == null)
        {
            return false; // There are no active networks.
        }
        else
        {
            return true;
        }
    }

    private String getInternetData(String uri, LinkedHashMap params) throws Exception
    {
//        BufferedReader in = null;
        String data = null;
        try
        {
            /* NEW Working */
//            String url = params[0];
            String USER_AGENT = "Mozilla/5.0";
            StringBuilder tokenUri = new StringBuilder();

            Iterator iterator = params.keySet().iterator();
            while (iterator.hasNext())
            {
                String key=(String)iterator.next();
                String value=(String)params.get(key);
                tokenUri.append(key + value);
            }

            URL obj = new URL(uri);
            HttpURLConnection con = (HttpURLConnection) obj.openConnection();

            con.setRequestMethod("POST");
            con.setRequestProperty("User-Agent", USER_AGENT);
            con.setRequestProperty("Accept-Language", "UTF-8");

            con.setDoOutput(true);
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(con.getOutputStream());
            outputStreamWriter.write(tokenUri.toString());
            outputStreamWriter.flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
            String inputLine;
            StringBuilder response = new StringBuilder();

            while ((inputLine = in.readLine()) != null)
            {
                response.append(inputLine);
            }
            in.close();

            data = response.toString();

            return data;
        }
        catch (Exception ex)
        {
            Utilities.handleException(ex);
            return data;
        }
//        finally
//        {
//            if (in != null)
//            {
//                try
//                {
//                    in.close();
//                    return data;
//                }
//                catch (Exception e)
//                {
//                    Utilities.handleException(e);
//                }
//            }
//        }
    }
}

最佳答案

首先,您需要在设备安全设置中安装自签名 SSL .cer 文件。 然后你需要添加一个network_security_config.xml并将其添加到您的 list 中。

android:networkSecurityConfig="@xml/network_security_config"

有几种配置网络安全的方法:ways to trust certificates . 我认为最好的方法是仅在调试时信任自定义 CA:

<network-security-config>  
  <debug-overrides>  
       <trust-anchors>  
            <!-- Trust user added CAs while debuggable only -->
            <certificates src="user" />  
       </trust-anchors>  
  </debug-overrides>  

但您也可以始终信任用户添加的 CA:

<network-security-config>
<base-config>
    <trust-anchors>
        <certificates src="system"/>
        <certificates src="user"/>
    </trust-anchors>
</base-config>

或者您可以指定哪些证书是可信的,here the marvelous description

关于java - Android - 由 : java. security.cert.CertPathValidatorException 引起:未找到证书路径的信任 anchor ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55106525/

相关文章:

java - Java 中的 Collection 和 Set 接口(interface)有什么区别?

java - 使用卡片布局,遇到一个我无法解决的问题

java - ViewPager 中 Fragment 内的 TextView 在方向更改时为空

ssl - 当您在表格中输入数据时,它是加密的吗?

java - Android 服务器应用程序 : SSLHandshakeException (unable to find valid certification path to requested target)

java - 什么是基于接口(interface)的框架?

android - 为什么我的自定义对象没有被 onSaveInstanceState 和 onRestoreInstanceState 持久化

android - 如何从状态栏中的 whatsapp 通知中提取消息文本?

amazon-web-services - 使用 AWS ELB 为带有自定义 ACM 证书的 HTTPS 流量配置 Istio Ingress

java - 解析 zip 或 Jar 项目