Подтвердить что ты не робот

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-домены терпят неудачу таким образом.

4b9b3361

Ответ 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