В моей ситуации, когда я запускаю программу на эмуляторе - ее работа коррелирует. Но когда я устанавливаю 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;
}
Это помогло мне создать надлежащую рабочую http-связь через ssl.
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, вы можете установить соединение
Вы можете переопределить сертификат веб-сервера с помощью addSLLCertificateToHttpRequest()
. addSLLCertificateToHttpRequest()
тем, как связаться с вашим сервером, 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();
}
}