【问题标题】:Android Https error Not trusted server certificateAndroid Https错误不受信任的服务器证书
【发布时间】:2012-02-26 06:16:31
【问题描述】:

在我在模拟器上运行 programm 的情况下 - 它的工作正常。 但是,当我将 apk 安装到手机时 - 出现错误 Not Trusted server certificate。 有什么问题?

我的 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;  
}

【问题讨论】:

  • 也许我应该在 keytool.bks 中使用 sertiftkat?如何制作和哪些文件?我有 crt 和 pem 文件。以及为什么没有他们模拟器工作?
  • 如果设备日期是 1970 年代等,有时会发生这种情况
  • 日期还好……就是现在的日期……
  • 看看这是否有帮助blog.crazybob.org/2010/02/…
  • 为什么你评论了 trustEveryone() ;我猜那是你的临时工作?

标签: android https


【解决方案1】:

这帮助我通过 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;                                    
}

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

【讨论】:

  • Android 2.3 以后的版本似乎没有受到同样程度的影响。这里的解决方案似乎更有安全意识,通过 Bouncy Castle 添加证书确实比信任所有人更好(这里是 gremlins)
  • 但我还有一个问题:我有两个文件 - file.crt 和 file.pem 。使用哪一个来创建存储库(KEYSTORE)?
【解决方案2】:

您可以使用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();
    }

}

【讨论】:

  • 我现在正在尝试。我在模拟器上的代码也有效。但在设备上 - 不是。
  • Muhhamad,这在模拟器上可以正常工作,设备目前没有......我以前使用过下面的代码,我认为他们正在做同样的工作,或者我 oshiayus?无论如何,非常感谢您对此作出回应。是否有这种情况离不开表?
  • 但我还有一个问题:我有两个文件 - file.crt 和 file.pem 。我用哪一个来创建存储库(KEYSTORE)?
  • 您好,我尝试了这些步骤,但仍然无法正常工作。 @Nabeel,你知道我应该如何继续吗?你想让我开始一个新问题吗?
猜你喜欢
  • 1970-01-01
  • 2014-11-29
  • 1970-01-01
  • 2020-11-14
  • 2011-08-01
  • 1970-01-01
  • 2012-05-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多