Phonegap Android-приложение ajax запрашивает HTTPS с статусом 0
Запросы Ajax HTTPS от моего приложения 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-домены терпят неудачу таким образом.
Ответы
Ответ 1
Это происходит, когда запрашиваемый 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();
}
}
-
in <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);
}
}
Et voilà! Ошибки SSL будут проигнорированы. Однако никогда не используйте ошибочные сертификаты. Попытайтесь исправить их сначала и использовать это грязное обходное решение только тогда, когда у вас заканчиваются другие решения.
Ответ 2
У меня была такая же проблема, но мое решение было немного другим.
-
Только в приложении Android App моего приложения Cordova AJAX звонки на мой сервер через HTTPS блокировались. Не в iOS, а не в настольных браузерах. Самое смутное, что в реальном Android-браузере вызовы HTTPS AJAX не будут работать.
-
Я проверил, что я могу сделать HTTPS-вызовы AJAX хорошо известным и доверенным URL-адресам, таким как https://google.com, а также обычные HTTP-вызовы на любой URL-адрес я заботиться о том, чтобы попробовать.
-
Это заставило меня поверить, что мой SSL-сертификат был либо НЕ установлен на 100% правильно, либо дешевый (~ $10 usd) cert из PositveSSL не был универсально доверенным ИЛИ и тем и другим.
-
Мой сертификат был установлен на моем балансировщике нагрузки AWS, поэтому я посмотрел вокруг, как я, возможно, испортил это, а также то, как PositiveSSL не был лучшим сертификатом для использования с точки зрения надежности. К счастью, я нашел статью, посвященную установке AWS ELB сертификатов. И они случайно использовали сертификат PositiveSSL! Внутри этой маленькой жемчужины:
"... Не обманывайтесь диалогом AWS, цепочка сертификатов действительно не является обязательной, когда ваш ELB разговаривает напрямую с браузером..."
http://www.nczonline.net/blog/2012/08/15/setting-up-ssl-on-an-amazon-elastic-load-balancer/
Drumroll....
Я переустановил сертификат с "необязательной" информацией о цепочке сертификатов и voilà!, вызовы HTTPS AJAX на мой сервер начали работать.
Итак, похоже, что Android Webview более консервативен, чем Android-браузер с точки зрения доверия к сертификату. Это не является полностью интуитивным, поскольку они должны быть в основном теми же технологиями.
Ответ 3
Другой вариант, который работает, также состоит в том, чтобы перекомпилировать базовый файл 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);
}
}
ПРИМЕЧАНИЕ. Я понимаю, что это небезопасно, но когда все остальное не удается, это решило проблему, которая продолжалась более двух месяцев, включая переустановку сертификата в соответствии с руководством по установке цепочки сертификатов, а рядом с ним находится сайт, который не является нашим 3rd party, так что независимо от того, действителен он или нет, он подключается только к этому серверу.
Ответ 4
Вы не можете использовать aples с поддержкой relese (phonegap) с самозаверяющими сертификатами. Посмотрите этот ответ, чтобы получить дополнительную информацию.
LG
fastrde