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

Android Https错误不受信任的服务器证书,android,https,Android,Https,在我的情况下,当我在emulator上运行程序时,它的工作是正确的。 但当我将apk安装到手机上时,出现错误“不信任服务器证书”。 有什么问题 我的AsyncTask有一个代码,用于向服务器发送响应: public abstract class BaseAsyncWorker extends AsyncTask<String, Void, String>{ public static final String AS = "BaseAsyncWorker"; private Stri

在我的情况下,当我在emulator上运行程序时,它的工作是正确的。 但当我将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;  
}
公共抽象类BaseAsyncWorker扩展AsyncTask{
公共静态最终字符串为=“BaseAsyncWorker”;
私有字符串URL;
私有字符串结果;
最终语境;
公共BaseAncyWorker(字符串url、上下文){
this.URL=URL;
this.context=上下文;
}
//以前
@凌驾
受保护的抽象void onPreExecute();
//背景
@凌驾
受保护的字符串doInBackground(字符串…对象){
用于(字符串对象:对象){
Log.d(AS,obj.toString());
日志d(作为“起始背景”);
appendLog(“启动响应…”);
试一试{
HostnameVerifier HostnameVerifier=SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
DefaultHttpClient=新的DefaultHttpClient();
SchemeRegistry registry=新SchemeRegistry();
SSLSocketFactory-socketFactory=SSLSocketFactory.getSocketFactory();
setHostnameVerifier((X509HostnameVerifier)hostnameVerifier);
register(新方案(“http”,PlainSocketFactory.getSocketFactory(),80));
注册(新方案(“https”,socketFactory,443));
SingleClientConnManager mngr=新建SingleClientConnManager(client.getParams(),
登记处);
//信任所有人();
DefaultHttpClient httpClient=新的DefaultHttpClient(mngr,client.getParams());
//MMGHttpClient-httpClient=新的MMGHttpClient(上下文);
//httpClient.getParams().setParameter(CoreProtocolPNames.USER_AGENT,“MyMobiGift Ltd.Android”);
//HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
HttpPost HttpPost=新的HttpPost(URL);
StringEntity se=新的StringEntity(obj);
httpPost.setEntity(se);
setHeader(“接受”、“应用程序/json”);
setHeader(“内容类型”、“应用程序/json”);
HttpResponse response=(HttpResponse)httpClient.execute(httpPost);
StatusLine status=response.getStatusLine();
如果((status.getStatusCode())==200){
HttpEntity=response.getEntity();
如果(实体!=null){
InputStream instream=entity.getContent();
结果=转换流到管柱(流内);
流内关闭();
expndtw-1.appendLog(“使用结果结束响应:“+result”);
}否则{
结果=空;
appendLog(“结束响应,无结果”);
}
}
}catch(ClientProtocolException e){Logger.appendLog(“ClientProtocolException位于”+e.getMessage();}
catch(IOException e){Logger.appendLog(“IOException位于”+e.getMessage());}
}   
返回结果;
}

您可以使用
addslCertificateTotHttpRequest()
方法覆盖Web服务器的证书。在与服务器通信之前调用
addslCertificateTotHttpRequest()
方法。这将避免证书失效并始终返回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();
    }

}

您可以使用
addsllcertificatetothttprequest()
方法覆盖Web服务器的证书。在与服务器通信之前调用
addsllcertificatetothttprequest()
方法。这将避免证书失效并始终返回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();
    }

}

这就是帮助我在ssl上构建正常工作的http通信的原因

如果您希望客户端(android设备)真正(而不是盲目地)信任主机,则需要将公共证书加载到设备的密钥库中,否则设备将无法与服务器通信

您将使用.crt文件,但要与Android密钥库一起使用,需要将其转换为“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;                                    
}

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

这就是帮助我通过ssl构建正常工作的http通信的原因

如果您希望客户端(android设备)真正(而不是盲目地)信任主机,则需要将公共证书加载到设备的密钥库中,否则设备将无法与服务器通信

您将使用.crt文件,但要与Android密钥库一起使用,需要将其转换为“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;                                    
}

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

也许我应该在keytool.bks中使用sertiftkat?如何制作以及哪些文件?我有crt和pem文件。为什么没有它们的情况下emulyator可以工作?如果设备的日期在20世纪70年代等等,有时会发生这种情况。好的日期…也就是说,是当前日期…see如果这有帮助,为什么你要评论trustEveryone();我猜这是你临时的工作?也许我应该在keytool.bks中使用sertiftkat?如何制作以及哪些文件?我有crt和pem文件。为什么没有它们的情况下emulyator工作?有时,如果设备的日期在20世纪70年代等等,就会出现这种情况。好的,日期就是当前日期…看看这是否有帮助,为什么你对每个人都发表了评论e();我猜那是你临时的工作?我现在正在尝试。我在emulator上的代码也工作了。但是在设备上-不是。Muhhamad,这是正确的工作在emulator上,设备目前没有…我以前使用过下面的代码,我想他们正在做相同的工作,或者我是oshiayus?无论如何,非常感谢您对我的回答o那。是否有这样的情况离不开表?但我还有一个问题:我有两个文件-file.crt和file.pem。使用哪一个来创建存储库(KEYSTORE)?H