Android Https 错误不受信任的服务器证书

发布于 2025-01-02 05:19:13 字数 3042 浏览 0 评论 0原文

在我的情况下,当我在模拟器上运行程序时 - 它可以正常工作。 但是当我将 apk 安装到手机时 - 出现错误“不受信任的服务器证书”。 问题是什么?

我的 AsyncTask 的代码用于向服务器发送响应:

public abstract class BaseAsyncWorker extends AsyncTask<String, Void, String>{
public static final String AS = "BaseAsyncWorker";
private  String URL;
private String result;
final Context context;

public BaseAsyncWorker(String url,Context context){
    this.URL = url; 
    this.context = context;
}
//before
@Override
protected abstract void onPreExecute();

//background
@Override
protected  String doInBackground(String... objects) {
    for (String obj : objects) {
        Log.d(AS,obj.toString() );
        Log.d(AS,"beginning background" );
        Logger.appendLog("Start response...");
        try{


            HostnameVerifier hostnameVerifier = SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;

            DefaultHttpClient client = new DefaultHttpClient();

            SchemeRegistry registry = new SchemeRegistry();
            SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
            socketFactory.setHostnameVerifier((X509HostnameVerifier)hostnameVerifier);
            registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
            registry.register(new Scheme("https", socketFactory,443));
            SingleClientConnManager mngr = new SingleClientConnManager(client.getParams(),
                                                                        registry);
            //trustEveryone();
            DefaultHttpClient httpClient = new DefaultHttpClient(mngr,client.getParams());

            //MMGHttpClient httpClient = new MMGHttpClient(context);
            //httpClient.getParams().setParameter(CoreProtocolPNames.USER_AGENT, "MyMobiGift Ltd. Android");
            //HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);

            HttpPost httpPost = new HttpPost(URL); 

            StringEntity se = new StringEntity(obj);
            httpPost.setEntity(se);
            httpPost.setHeader("Accept", "application/json");
            httpPost.setHeader("Content-type", "application/json");



            HttpResponse response = (HttpResponse)httpClient.execute(httpPost);
            StatusLine status = response.getStatusLine();
            if((status.getStatusCode())==200){
                HttpEntity entity = response.getEntity();
                if(entity!=null){
                    InputStream instream = entity.getContent();
                    result= convertStreamToString(instream);
                    instream.close();
                    Logger.appendLog("End response with result: "+result);
                }else{
                    result=null;
                    Logger.appendLog("End response without result");
                }
            }
        }catch (ClientProtocolException e) {Logger.appendLog("ClientProtocolException at"+e.getMessage());}
        catch (IOException e) {Logger.appendLog("IOException at" + e.getMessage());}

    }   
    return result;  
}

In my situation when I run programm on emulator - its work correktly.
But when I install apk to phone - have error Not trusted server certificate.
What is the problem?

there is a code of my AsyncTask for sending response to the server:

public abstract class BaseAsyncWorker extends AsyncTask<String, Void, String>{
public static final String AS = "BaseAsyncWorker";
private  String URL;
private String result;
final Context context;

public BaseAsyncWorker(String url,Context context){
    this.URL = url; 
    this.context = context;
}
//before
@Override
protected abstract void onPreExecute();

//background
@Override
protected  String doInBackground(String... objects) {
    for (String obj : objects) {
        Log.d(AS,obj.toString() );
        Log.d(AS,"beginning background" );
        Logger.appendLog("Start response...");
        try{


            HostnameVerifier hostnameVerifier = SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;

            DefaultHttpClient client = new DefaultHttpClient();

            SchemeRegistry registry = new SchemeRegistry();
            SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
            socketFactory.setHostnameVerifier((X509HostnameVerifier)hostnameVerifier);
            registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
            registry.register(new Scheme("https", socketFactory,443));
            SingleClientConnManager mngr = new SingleClientConnManager(client.getParams(),
                                                                        registry);
            //trustEveryone();
            DefaultHttpClient httpClient = new DefaultHttpClient(mngr,client.getParams());

            //MMGHttpClient httpClient = new MMGHttpClient(context);
            //httpClient.getParams().setParameter(CoreProtocolPNames.USER_AGENT, "MyMobiGift Ltd. Android");
            //HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);

            HttpPost httpPost = new HttpPost(URL); 

            StringEntity se = new StringEntity(obj);
            httpPost.setEntity(se);
            httpPost.setHeader("Accept", "application/json");
            httpPost.setHeader("Content-type", "application/json");



            HttpResponse response = (HttpResponse)httpClient.execute(httpPost);
            StatusLine status = response.getStatusLine();
            if((status.getStatusCode())==200){
                HttpEntity entity = response.getEntity();
                if(entity!=null){
                    InputStream instream = entity.getContent();
                    result= convertStreamToString(instream);
                    instream.close();
                    Logger.appendLog("End response with result: "+result);
                }else{
                    result=null;
                    Logger.appendLog("End response without result");
                }
            }
        }catch (ClientProtocolException e) {Logger.appendLog("ClientProtocolException at"+e.getMessage());}
        catch (IOException e) {Logger.appendLog("IOException at" + e.getMessage());}

    }   
    return result;  
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情魔剑神 2025-01-09 05:19:13

这帮助我通过 ssl 建立正确的 http 通信。

http://blog.antoine.li/2010/10/ 22/android-trusting-ssl-certificates/

如果你想让客户端(android设备)真正(不是盲目地)信任主机,需要将公共证书加载到设备的KeyStore中,否则设备不会与服务器对话

您将使用 .crt 文件,但要与 Android KeyStore 一起使用,您需要将其转换为“bks”。我执行以下操作:

// read .crt file from memory
InputStream inStream = ctx.openFileInput("cetificate.crt");

//InputStream inStream = ctx.getAssets().open("wm_loaner.cer");
if(inStream != null)
{
    KeyStore cert = CertUtils.ConvertCerToBKS(inStream, "MyAlias", "password".toCharArray());
    inStream.close();
}

public static KeyStore ConvertCerToBKS(InputStream cerStream, String alias, char [] password)
{
    KeyStore keyStore = null;
    try
    {
        keyStore = KeyStore.getInstance("BKS", "BC");
        CertificateFactory factory = CertificateFactory.getInstance("X.509", "BC");
        Certificate certificate = factory.generateCertificate(cerStream);
        keyStore.load(null, password);
        keyStore.setCertificateEntry(alias, certificate);
    }
    catch ....
    {
    }
    return keyStore;                                    
}

证书转换并加载到密钥库后,您可以建立连接

This is what helped me to build a proper working http communication over ssl.

http://blog.antoine.li/2010/10/22/android-trusting-ssl-certificates/

If you want client (android device) really (not blindly) trusts host, public certificate needs to be loaded to device's KeyStore, otherwise device won't talk to the server

You will use .crt file but to use with Android KeyStore you need it to be converted to "bks". I do following:

// read .crt file from memory
InputStream inStream = ctx.openFileInput("cetificate.crt");

//InputStream inStream = ctx.getAssets().open("wm_loaner.cer");
if(inStream != null)
{
    KeyStore cert = CertUtils.ConvertCerToBKS(inStream, "MyAlias", "password".toCharArray());
    inStream.close();
}

public static KeyStore ConvertCerToBKS(InputStream cerStream, String alias, char [] password)
{
    KeyStore keyStore = null;
    try
    {
        keyStore = KeyStore.getInstance("BKS", "BC");
        CertificateFactory factory = CertificateFactory.getInstance("X.509", "BC");
        Certificate certificate = factory.generateCertificate(cerStream);
        keyStore.load(null, password);
        keyStore.setCertificateEntry(alias, certificate);
    }
    catch ....
    {
    }
    return keyStore;                                    
}

After certificate was converted and loaded to the KeyStore you can establish a connection

乱世争霸 2025-01-09 05:19:13

您可以使用 addSLLCertificateToHttpRequest() 方法覆盖网络服务器的证书。在与服务器通信之前调用 addSLLCertificateToHttpRequest() 方法。这将避免证书失效并始终返回 true。我正在写这个方法。这对我有用

/**
 * The server has a SSL certificate. This method add SSL certificate to HTTP
 * Request
 */
public static void addSLLCertificateToHttpRequest() {
    // Code to use verifier which return true.
    try {
        SSLContext sslctx = null;
        try {
            sslctx = SSLContext.getInstance("TLS");
            sslctx.init(null, new TrustManager[] { new X509TrustManager() {
                public void checkClientTrusted(X509Certificate[] chain, String authType)
                {
                }

                public void checkServerTrusted(X509Certificate[] chain, String authType)
                {
                }

                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[] {};
                }
            } }, null);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        HttpsURLConnection.setDefaultSSLSocketFactory(sslctx.getSocketFactory());
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });
    } catch (Exception e) {
        e.printStackTrace();
    }

}

You can override certificate of webserver by using addSLLCertificateToHttpRequest() method. Call addSLLCertificateToHttpRequest() method before communicating with your server. This will avoid certificate invalidation and always return true. I am writing this method. This is working for me

/**
 * The server has a SSL certificate. This method add SSL certificate to HTTP
 * Request
 */
public static void addSLLCertificateToHttpRequest() {
    // Code to use verifier which return true.
    try {
        SSLContext sslctx = null;
        try {
            sslctx = SSLContext.getInstance("TLS");
            sslctx.init(null, new TrustManager[] { new X509TrustManager() {
                public void checkClientTrusted(X509Certificate[] chain, String authType)
                {
                }

                public void checkServerTrusted(X509Certificate[] chain, String authType)
                {
                }

                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[] {};
                }
            } }, null);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        HttpsURLConnection.setDefaultSSLSocketFactory(sslctx.getSocketFactory());
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });
    } catch (Exception e) {
        e.printStackTrace();
    }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文