Android WebView 未加载 HTTPS URL
Posted
技术标签:
【中文标题】Android WebView 未加载 HTTPS URL【英文标题】:Android WebView not loading an HTTPS URL 【发布时间】:2011-11-16 23:34:57 【问题描述】:public void onCreate(Bundle savedInstance)
super.onCreate(savedInstance);
setContentView(R.layout.show_voucher);
webView=(WebView)findViewById(R.id.webview);
webView.getSettings().setjavascriptEnabled(true);
webView.getSettings().setBuiltInZoomControls(true);
String url ="https://www.paymeon.com/Vouchers/?v=%C80%8D%B1x%D9%CFqh%FA%84%C35%0A%1F%CE&iv=%25%EE%BEi%F4%DAT%E1"
//webView.loadUrl(url); // Not Working... Showing blank
webView.loadUrl("http://www.yahoo.com"); // its working
当我尝试在 WebBView 中加载 URL 时,它只显示一个空白屏幕。如果我加载 Google.com 或 yahoo.com,它工作正常。
【问题讨论】:
我现在检查了它的工作。再次检查是否无法使用您的代码添加此代码 webView.getSettings().setUseWideViewPort(true); webView.getSettings().setLoadWithOverviewMode(true); 【参考方案1】:Please visit this link:
将此覆盖方法添加到您的 WebViewClient 实现中。您需要使用 android SDK 2.2(API 级别 8)或更高版本对其进行编译。该方法从 2.2(API 级别 8)开始出现在公共 SDK 中,但我们已经在运行 2.1、1.6 和 1.5 的设备上对其进行了测试,并且它也可以在这些设备上运行(显然这种行为一直存在)。
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error)
handler.proceed(); // Ignore SSL certificate errors
这会对你有所帮助。
【讨论】:
讨论中的最后一个条目效果很好。非常感谢。 安全警告:请注意,这样做完全违背了最初使用 SSL 的目的。 请不要这样做。这是不安全的,不允许在 Play 商店中使用。 Google 现在正在向实施上述解决方案的人发送电子邮件:Your app(s) listed at the end of this email have an unsafe implementation of the WebViewClient.onReceivedSslError handler. Specifically, the implementation ignores all SSL certificate validation errors, making your app vulnerable to man-in-the-middle attacks.
Apps with vulnerabilities that expose users to risk of compromise may be considered Dangerous Products in violation of the Content Policy and section 4.4 of the Developer Distribution Agreement.
任何人都知道如何解决谷歌安全警告,如果是,请告诉我,因为我也面临这个问题。【参考方案2】:
根据正确答案,以下是一个可能有帮助的小代码示例。
首先,创建一个扩展 WebViewClient 并设置为忽略 SSL 错误的类:
// SSL Error Tolerant Web View Client
private class SSLTolerentWebViewClient extends WebViewClient
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error)
handler.proceed(); // Ignore SSL certificate errors
然后使用您的 Web 视图对象(在 OnCreate() 方法中启动),将其 Web 视图客户端设置为覆盖类的实例:
mWebView.setWebViewClient(
new SSLTolerentWebViewClient()
);
【讨论】:
这给出了谷歌安全警告:WebViewClient.onReceivedSslError 处理程序的不安全实现。你知道如何解决这个问题吗? Google 在 Playstore 上将应用程序标记为 Unsaif,没有 ssl 怎么办? 不要使用Super方法- super.onReceivedSslError(view, handler, error); 它适用于普通网页,但是当我尝试为 youtube 视频加载 iframe 时它不起作用..【参考方案3】:为了根据新的安全政策正确处理 SSL 证书验证并避免 Google 拒绝应用程序,请更改您的代码以在服务器提供的证书符合您的期望时调用 SslErrorHandler.proceed(),否则调用 SslErrorHandler.cancel()。
例如,我添加了一个警告对话框以使用户确认并且似乎 Google 不再显示警告。
@Override
public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error)
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
String message = "SSL Certificate error.";
switch (error.getPrimaryError())
case SslError.SSL_UNTRUSTED:
message = "The certificate authority is not trusted.";
break;
case SslError.SSL_EXPIRED:
message = "The certificate has expired.";
break;
case SslError.SSL_IDMISMATCH:
message = "The certificate Hostname mismatch.";
break;
case SslError.SSL_NOTYETVALID:
message = "The certificate is not yet valid.";
break;
message += " Do you want to continue anyway?";
builder.setTitle("SSL Certificate Error");
builder.setMessage(message);
builder.setPositiveButton("continue", new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface dialog, int which)
handler.proceed();
);
builder.setNegativeButton("cancel", new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface dialog, int which)
handler.cancel();
);
final AlertDialog dialog = builder.create();
dialog.show();
更改后不会显示警告。
【讨论】:
如果我从实现中删除 onReceivedSslError 块会发生什么? @VivekSinha 它将调用 handler.cancel();默认情况下。 但谷歌仍然以同样的理由拒绝了我的应用程序。为什么? @VivekSinha 找到有关在 Play 商店中启动应用的任何解决方案? 我按照建议实现了 onReceivedSslError 回调。之后应用发布成功。【参考方案4】:覆盖 onReceivedSslError 并删除
super.onReceivedSslError(视图、处理程序、错误)
并解决谷歌安全问题:
setDomStorageEnabled(true);
完整代码为:
webView.enableJavaScript();
webView.getSettings().setDomStorageEnabled(true); // Add this
webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
webView.setWebViewClient(new WebViewClient()
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error)
// DO NOT CALL SUPER METHOD
super.onReceivedSslError(view, handler, error);
);
【讨论】:
非常感谢您。删除 super.onReceivedSslError(view, handler, error) 对我有用。【参考方案5】:删除下面的代码就行了
super.onReceivedSslError(view, handler, error);
【讨论】:
太好了,它对我有用。你能解释一下它是如何工作的吗? @ArthTilva 来自谷歌文档:“默认行为是取消加载”。通过调用 super 您在调用该默认行为之前,它可以到达方法的其余部分。 developer.android.com/reference/android/webkit/…【参考方案6】:复制并粘贴您的代码行兄弟,相信我,它会起作用:) 我在想,您会收到 ssl 错误。如果您使用覆盖 onReceivedSslError 方法并删除 super 它是超级方法。只要写 handler.proceed() ,错误就会解决。
webView.setWebChromeClient(new WebChromeClient()
public void onProgressChanged(WebView view, int progress)
activity.setTitle("Loading...");
activity.setProgress(progress * 100);
if (progress == 100)
activity.setTitle(getResources().getString(R.string.app_name));
);
webView.setWebViewClient(new WebViewClient()
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl)
Log.d("Failure Url :" , failingUrl);
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error)
Log.d("Ssl Error:",handler.toString() + "error:" + error);
handler.proceed();
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
view.loadUrl(url);
return true;
);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setLoadWithOverviewMode(true);
webView.getSettings().setUseWideViewPort(true);
webView.getSettings().setDomStorageEnabled(true);
webView.loadUrl(Constant.VIRTUALPOS_URL + "token=" + Preference.getInstance(getContext()).getToken() + "&dealer=" + Preference.getInstance(getContext()).getDealerCode());
【讨论】:
谢谢。在onReceivedSslError
中调用 handler.proceed() 保存我的一天
如果您这样做(现在是 2019 年 7 月),Google Play 将拒绝您的申请。
© google play 上的应用程序太多,没有一个应用程序仍然被拒绝。
将拒绝 2020 年 1 月的 on-words【参考方案7】:
我遵循了上面的答案,但在集成通常是 https 请求的支付网关时,下面的代码似乎对我不起作用:
public class MainActivity extends Activity
WebView webView;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = (WebView) findViewById(R.id.webView1);
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setDomStorageEnabled(true);
webView.setWebViewClient(new MyWebViewClient());
String postData = "amount=1000&firstname=mtetno&email=mttee@gmail.com&phone=2145635784&productinfo=android&surl=success.php"
+ "&furl=failure.php&lastname=qwerty&curl=dsdsd.com&address1=dsdsds&address2=dfdfd&city=dsdsds&state=dfdfdfd&"
+ "country=fdfdf&zipcode=123456&udf1=dsdsds&udf2=fsdfdsf&udf3=jhghjg&udf4=fdfd&udf5=fdfdf&pg=dfdf";
webView.postUrl(
"http://host/payment.php",
EncodingUtils.getBytes(postData, "BASE64"));
private class MyWebViewClient extends WebViewClient
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
webView.loadUrl(url);
return true;
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler,
SslError error)
handler.proceed();
上面的代码在 webview 中做一个 post 请求并重定向到支付网关。
设置settings.setDomStorageEnabled(true);
对我有用
希望这会有所帮助。
【讨论】:
此解决方案完全禁用证书验证,让您容易受到中间人攻击。这是你不应该做的事情,特别是对于支付网关。 对我来说,最初的 webview 并没有加载内容,而只是页面的背景图像。在我刚刚添加webview.getSettings.setDomStorageEnabled(true);
之后,它神奇地起作用了。也许网页正在使用某种 html 5 API,所以启用 DomStorage 对我有用。
handler.proceed() 绕过 SSL
什么是 Encodingutil.getbyte【参考方案8】:
要处理 SSL url,请使用 WebViewClient 类中的方法 onReceivedSslError(),这是一个示例:
webview.setWebViewClient(new WebViewClient()
...
...
...
@Override
public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error)
String message = "SSL Certificate error.";
switch (error.getPrimaryError())
case SslError.SSL_UNTRUSTED:
message = "The certificate authority is not trusted.";
break;
case SslError.SSL_EXPIRED:
message = "The certificate has expired.";
break;
case SslError.SSL_IDMISMATCH:
message = "The certificate Hostname mismatch.";
break;
case SslError.SSL_NOTYETVALID:
message = "The certificate is not yet valid.";
break;
message += "\"SSL Certificate Error\" Do you want to continue anyway?.. YES";
handler.proceed();
);
您可以在此处查看我的完整示例: https://github.com/Jorgesys/Android-WebView-Logging
【讨论】:
【参考方案9】:要解决 Google 安全问题,请执行以下操作:
到顶部的行:
import android.webkit.SslErrorHandler;
import android.net.http.SslError;
代码:
class SSLTolerentWebViewClient extends WebViewClient
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error)
if (error.toString() == "piglet")
handler.cancel();
else
handler.proceed(); // Ignore SSL certificate errors
【讨论】:
我是 Android 新手。我应该把这个放在哪里? :)【参考方案10】:推荐的方法是
1.不要调用 super 方法(从被覆盖的方法中移除 super 调用)
2.如果出现错误,Google 建议调用 SslErrorHandler.cancel() 方法
3.不提示对话框暴露 SSL 错误
什么是最好的解决方案?? 去掉这个覆盖方法
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler,SslError error)
【讨论】:
您是在寻求解决方案还是提出建议? 我建议采用这种方法 @JohnRubanSingh 嗨,约翰,我已经从资产加载了一个 JS 文件,一旦用 onPageFinished 加载文件,我就会在 JS 中调用一个函数。所以,重写 onReceivedSslError() 是必要的,因为我正在使用 webview.setWebViewClient(new ....) ? 这段代码拒绝了我的 APK。即使从 9 个月以来,这段代码也没有导致拒绝,而是突然面临拒绝 r8。 switch (error.getPrimaryError()) case SslError.SSL_UNTRUSTED: handler.proceed();休息; case SslError.SSL_EXPIRED: case SslError.SSL_IDMISMATCH: case SslError.SSL_NOTYETVALID: case SslError.SSL_DATE_INVALID: case SslError.SSL_INVALID: default: handler.cancel();休息; @JohnRubanSingh 请帮助我。我们可以加入 slack。【参考方案11】:如果您想在 Google Play 商店之外使用 APK,例如,私有解决方案可能会起作用,如下所示:
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error)
/*...*/
handler.proceed();
如果您想添加额外的可选安全层,您可以尝试使用certificate pinning。恕我直言,这对于私人或内部使用来说不是必需的。
如果您打算在 Google Play 商店上发布应用程序,那么您应该避免 @Override onReceivedSslError(...)...。尤其是使用 handler.proceed()。 Google 会找到这段代码 sn-p 并且肯定会拒绝您的应用,因为带有 handler.proceed() 的解决方案 会抑制各种内置的安全性机制。
因为浏览器不会抱怨你的 https连接,并不代表SSL证书本身就是 完全信任!
就我而言,SSL certificate chain 已损坏。您可以使用SSL Checker 快速测试此类问题,或者使用SSLLabs 快速测试此类问题。但请不要问我这是怎么发生的。我完全不知道。
无论如何,在重新安装 SSL 证书后,所有关于“WebView 中不受信任的 SSL 证书”的错误最终都消失了。 我还删除了 onReceivedSslError(...) 的 @Override 并删除了 handler.proceed(),然后我的应用没有被 Google Play 商店拒绝(再次)。
【讨论】:
【参考方案12】:我的网站是在 angular 8 上开发的子域,它也使用本地存储和 cookie。设置以下行后显示的网站以及上述其他解决方案。
webSettings.setDomStorageEnabled(true);
【讨论】:
【参考方案13】:设置这两个属性足以让它对我有用,并且不会暴露安全问题:
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setDomStorageEnabled(true);
【讨论】:
【参考方案14】:在你的java代码中使用这一行webview.getSettings().setDomStorageEnabled(true)
WebView webView = (WebView) findViewById(R.id.webview);
webView.getSettings().setDomStorageEnabled(true);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webView.loadUrl(yourUrl);
【讨论】:
【参考方案15】:在清单中的应用程序标签中添加 android:usesCleartextTraffic="true" 一切都会好的。这对我有用。
【讨论】:
好像是评论【参考方案16】:检查你的用户代理,如果太长你应该得到这个错误
【讨论】:
这并没有提供问题的答案,这将更适合作为评论。以上是关于Android WebView 未加载 HTTPS URL的主要内容,如果未能解决你的问题,请参考以下文章
Webview android中的Paypal支付页面布局损坏可能css未正确加载?
Youtube 视频未加载到 android 的 webview 中
HTML5 - 在 Android WebView 中首次加载时未呈现画布
Android WebView 混合内容未在 api 级别 < 21 中加载