来自Android上的PhoneGap / Cordova应用程序的Ajax HTTPS请求莫名其妙地失败,状态= 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商店或使用adb
实用程序安装应用程序并不重要。我认为它可以与证书连接,因为并非所有HTTPS域都以这种方式失败。
答案 0 :(得分:13)
我遇到了同样的问题,但我的解决方案有点不同。
仅在我的Cordova应用程序的Android App版本中,通过HTTPS调用我的服务器的AJAX被阻止。不在iOS中,不在桌面浏览器中。最令人困惑的是,在实际的Android浏览器中,HTTPS AJAX调用没有问题。
我确认我可以对知名且可信赖的URL(例如https://google.com)进行HTTPS AJAX调用,也可以对我认真尝试的任何网址进行常规HTTP调用。
这让我相信我的SSL证书要么没有100%正确安装,要么PositveSSL的廉价(〜$ 10美元)证书不是普遍信任的,或两者兼而有之。
我的证书已安装在我的AWS Load Balancer上,因此我查看了我可能如何搞砸了这一点,以及PositiveSSL如何在可信度方面不是最佳证书。 Lucky me发现了一篇涵盖AWS ELB安装证书的文章,他们碰巧使用的是PositiveSSL证书!其中包含了这个小宝石:
“......不要被AWS对话框欺骗,当您的ELB直接与浏览器交谈时,证书链不是真正可选的......”
http://www.nczonline.net/blog/2012/08/15/setting-up-ssl-on-an-amazon-elastic-load-balancer/
<强>击鼓声... 强>
我重新安装了带有“可选”证书链信息的证书,并且voilà!,我的服务器的HTTPS AJAX调用开始工作。
因此,在证书信任方面,Android Webview似乎比Android浏览器更保守。这并不完全直观,因为它们应该基本上是相同的技术。
答案 1 :(得分:6)
当请求的URL以错误或自签名证书响应时,会发生这种情况。在向朋友测试或分发应用时,在<application android:debuggable="true"...>
中设置AndroidManifest.xml
就足够了 - 它会自动绕过证书错误。
但Google Play商店不接受android:debuggable="true"
的APK。首先,证书当然需要修复。但是当发生这种情况时,这是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);
}
}
醇>
Etvoilà! SSL错误将被忽略。但是,永远不要使用错误的证书。尝试先修复它们,只有在用完其他解决方案时才使用这个脏的解决方法。
答案 2 :(得分:4)
另一个可行的选项是重新编译底层的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个月的问题,包括在证书链安装指南之后重新安装证书,旁边是一个我们自己没有的网站第三方所以无论是否有效它都只是连接到这个服务器。
答案 3 :(得分:1)
在我的情况下,它是一个缺少的中间证书,我必须在我的网络服务器上安装。您必须牢记这一点,尤其是在使用廉价证书时。
如果您的证书链正确,您可以在线轻松查看,您可以在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
答案 4 :(得分:0)