Android-приложение Phonegap ajax запрашивает HTTPS с ошибкой со статусом 0
HTTPS-запросы Ajax из моего приложения PhoneGap/Cordova на Android по необъяснимым причинам завершаются сбоем со статусом =0. Он появляется только при подписании приложения с помощью ключа разблокировки (т. Е. При экспорте из ADT), но не отображается при подписи с помощью ключа отладки (работает непосредственно в эмуляторе или на телефоне).
request = new XMLHttpRequest()
request.open "GET", "https://some.domain/", true
request.onreadystatechange = ->
console.log "** state = " + request.readyState
if request.readyState is 4
console.log "** status = " + request.status
request.send()
всегда выводит
** state = 4
** status = 0
Неважно, если я устанавливаю приложение из Play Store или с adb
полезность. Я предполагаю, что это может быть связано с сертификатом, так как не все домены HTTPS терпят неудачу таким образом.
5 ответов
Это происходит, когда запрошенный URL-адрес отвечает ошибочным или самозаверяющим сертификатом. Во время тестирования или распространения приложения среди друзей, настройка <application android:debuggable="true"...>
в AndroidManifest.xml
достаточно - он автоматически обходит ошибки сертификата.
Но Google Play Store не примет APK с android:debuggable="true"
, Прежде всего, сертификаты, конечно, должны быть исправлены. Но пока это происходит, вот обходной путь для PhoneGap/Cordova 3:
В вашем пакете приложения создайте подкласс для
CordovaWebViewClient
:public class SSLAcceptingCordovaWebViewClient extends CordovaWebViewClient { public SSLAcceptingCordovaWebViewClient(CordovaInterface cordova, CordovaWebView view) { super(cordova, view); } @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { handler.proceed(); } }
То же самое для
IceCreamCordovaWebViewClient
:public class SSLAcceptingIceCreamCordovaWebViewClient extends IceCreamCordovaWebViewClient { public SSLAcceptingIceCreamCordovaWebViewClient(CordovaInterface cordova, CordovaWebView view) { super(cordova, view); } @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { handler.proceed(); } }
в
<Your App Name>.java
добавить переопределение дляmakeWebViewClient
:@Override protected CordovaWebViewClient makeWebViewClient(CordovaWebView webView) { if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) { return new SSLAcceptingCordovaWebViewClient(this, webView); } else { return new SSLAcceptingIceCreamCordovaWebViewClient(this, webView); } }
И вуаля! Ошибки SSL будут игнорироваться. Однако никогда не используйте ошибочные сертификаты. Попробуйте сначала исправить их и используйте этот грязный обходной путь только тогда, когда у вас закончатся другие решения.
У меня была та же проблема, но мое решение было немного другим.
Только в сборке приложения Android для моего приложения Cordova вызовы AJAX на мой сервер через HTTPS блокировались. Не в iOS, не в настольных браузерах. Самое странное, что в реальном браузере Android вызовы HTTPS AJAX не будут работать без проблем.
Я подтвердил, что могу делать HTTPS AJAX-вызовы на хорошо известные и надежные URL-адреса, такие как https://google.com/ а также регулярные HTTP-вызовы на любой URL-адрес, который мне хотелось попробовать.
Это заставило меня поверить, что мой SSL-сертификат либо НЕ был установлен на 100% правильно, либо дешевым (~ 10 долларов США) сертификатом от PositveSSL не был универсально доверенным, ИЛИ ни тем, ни другим.
Мой сертификат был установлен на AWS Load Balancer, поэтому я огляделся по поводу того, как, возможно, я все испортил, а также по поводу того, что PositiveSSL был не лучшим сертификатом для использования с точки зрения надежности. К счастью, я нашел статью, посвященную установке сертификатов AWS ELB, и они использовали сертификат PositiveSSL! Внутри был этот маленький драгоценный камень:
"... Не обманывайтесь диалогом AWS, цепочка сертификатов не является обязательной, когда ваш ELB общается напрямую с браузером..."
http://www.nczonline.net/blog/2012/08/15/setting-up-ssl-on-an-amazon-elastic-load-balancer/
Барабанная дробь....
Я переустановил сертификат с "дополнительной" информацией о цепочке сертификатов и вуаля! HTTPS AJAX-звонки на мой сервер начали работать.
Таким образом, кажется, что веб-представление Android является более консервативным, чем браузер Android с точки зрения доверия. Это не совсем интуитивно понятно, поскольку предполагается, что они в основном одни и те же технологии.
Другой вариант, который также работает, - это перекомпилировать базовый файл cordova.jar, чтобы тест был полностью удален, поэтому нет причин беспокоиться о том, что ваш сертификат действителен или нет. Я столкнулся с проблемой из-за того, что Android не распознает сертификат GoDaddy, который был на сервере. Сертификат показывает действительный на iOS, но даже при просмотре с Android жаловался на сертификат. Это из ветки 2.9.x, так как это то, с чем я работал.
cordova-android / framework / src / org / apache / cordova / CordovaWebViewClient.java
@TargetApi(8)
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
final String packageName = this.cordova.getActivity().getPackageName();
final PackageManager pm = this.cordova.getActivity().getPackageManager();
ApplicationInfo appInfo;
try {
appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
handler.proceed();
return;
/* REMOVED TO BY PASS INVALID CERT CHAIN ****
if ((appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
// debug = true
handler.proceed();
return;
} else {
// debug = false
super.onReceivedSslError(view, handler, error);
}*/
} catch (NameNotFoundException e) {
// When it doubt, lock it out!
super.onReceivedSslError(view, handler, error);
}
}
ПРИМЕЧАНИЕ. Я понимаю, что это небезопасно, но когда все остальное не помогло, это решило проблему, которая продолжалась в течение более 2 месяцев, включая переустановку сертификата в соответствии с руководством по установке цепочки сертификатов, и рядом с ним находится сайт, который является нашей собственной, а не третьей стороной, поэтому независимо от того, действителен он или нет, он подключается только к этому серверу.
В моем случае это был отсутствующий промежуточный сертификат, который я должен был установить на своем веб-сервере. Вы должны иметь это в виду, особенно когда вы используете дешевые сертификаты.
Вы можете легко проверить это онлайн, если ваша цепочка сертификатов правильная, вы найдете много на Google, например, https://www.sslshopper.com/ssl-checker.html
В Apache2 это часть директивы VirtualHost 443, в вашей директиве есть три правила, это выглядит так:
SSLCertificateFile /etc/apache2/ssl/mycert.crt
SSLCertificateKeyFile /etc/apache2/ssl/mykey.key
SSLCertificateChainFile /etc/apache2/ssl/certification_auth_intermediate.crt
Вы не можете использовать готовые (phonegap) apks с самозаверяющими сертификатами. Посмотрите на этот ответ, чтобы получить дополнительную информацию.
Л.Г.
fastrde