我有一个将在WebView中打开的链接。问题是,除非我像这样覆盖onReceivedSslError,否则它无法打开:
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed();
}我从Google Play收到了安全警告,上面写着:
安全警报您的应用程序有WebViewClient.onReceivedSslError处理程序的不安全实现。具体来说,该实现忽略了所有SSL证书验证错误,使您的应用程序容易受到中间人攻击.攻击者可以更改受影响的WebView的内容,读取传输的数据(例如登录凭据),并使用JavaScript在应用程序中执行代码。 要正确处理SSL证书验证,请更改代码,以便在服务器提供的证书满足您的期望时调用SslErrorHandler.proceed(),否则调用SslErrorHandler.cancel()。包含受影响应用程序和类(Es)的电子邮件警报已发送到您的开发人员帐户地址。 请尽快解决此漏洞,并增加升级APK的版本号。有关SSL错误处理程序的更多信息,请参见开发人员帮助中心中的文档。对于其他技术问题,您可以在https://www.stackoverflow.com/questions上发布并使用标签“android”和“SslErrorHandler”。如果你使用的是一个第三方图书馆,负责这一点,请通知第三方,并与他们合作,以解决这一问题。 要确认升级是否正确,请将更新后的版本上传到开发人员控制台,并在5个小时后进行检查。如果应用程序没有被正确升级,我们将显示一个警告。 请注意,虽然这些特定的问题可能不会影响到所有使用WebView SSL的应用程序,但最好在所有安全修补程序上保持最新的状态。有漏洞的应用程序会使用户面临妥协的风险,这可能被认为是违反内容策略和开发人员分发协议第4.4节的危险产品。 请确保所有发布的应用程序符合开发人员分发协议和内容策略。如果您有问题或关切,请联系我们的支持团队通过谷歌游戏开发人员帮助中心。
如果我删除了onReceivedSslError (handler.proceed()),那么页面就不会打开。
有什么方法可以在WebView 中打开页面并避免安全警报?
发布于 2016-03-22 06:53:03
要正确处理SSL证书验证,请更改代码,以便在服务器提供的证书满足您的期望时调用SslErrorHandler.proceed(),否则调用SslErrorHandler.cancel()。
正如电子邮件所说的,onReceivedSslError应该处理用户使用无效证书的页面,比如一个通知对话框。你不应该直接去做。
例如,我添加了一个警报对话框,以使用户已经确认,似乎谷歌不再显示警告。
@Override
public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(R.string.notification_error_ssl_cert_invalid);
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();
}更多关于电子邮件的解释。
具体来说,该实现忽略了所有SSL证书验证错误,使您的应用程序容易受到中间人攻击.
电子邮件说默认实现忽略了一个重要的SSL安全问题。所以我们需要在我们自己的应用程序中处理它,它使用了WebView。使用警报对话框通知用户是一种简单的方法。
发布于 2018-04-05 14:24:50
到目前为止,所提出的解决方案只是绕过了安全检查,所以它们并不安全。
我建议的是将证书嵌入应用程序中,当发生SslError时,检查服务器证书是否与嵌入的证书之一匹配。
下面是几个步骤:
- Open the site on Safari
- Click on the padlock icon near the website name
- Click on Show Certificate
- Drag and drop the certificate in a folder
请参阅https://www.markbrilman.nl/2012/03/howto-save-a-certificate-via-safari-on-mac/
发布于 2017-10-18 14:19:33
在向用户显示任何消息之前,我需要检查我们的信任库,所以我这样做了:
public class MyWebViewClient extends WebViewClient {
private static final String TAG = MyWebViewClient.class.getCanonicalName();
Resources resources;
Context context;
public MyWebViewClient(Resources resources, Context context){
this.resources = resources;
this.context = context;
}
@Override
public void onReceivedSslError(WebView v, final SslErrorHandler handler, SslError er){
// first check certificate with our truststore
// if not trusted, show dialog to user
// if trusted, proceed
try {
TrustManagerFactory tmf = TrustManagerUtil.getTrustManagerFactory(resources);
for(TrustManager t: tmf.getTrustManagers()){
if (t instanceof X509TrustManager) {
X509TrustManager trustManager = (X509TrustManager) t;
Bundle bundle = SslCertificate.saveState(er.getCertificate());
X509Certificate x509Certificate;
byte[] bytes = bundle.getByteArray("x509-certificate");
if (bytes == null) {
x509Certificate = null;
} else {
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
Certificate cert = certFactory.generateCertificate(new ByteArrayInputStream(bytes));
x509Certificate = (X509Certificate) cert;
}
X509Certificate[] x509Certificates = new X509Certificate[1];
x509Certificates[0] = x509Certificate;
trustManager.checkServerTrusted(x509Certificates, "ECDH_RSA");
}
}
Log.d(TAG, "Certificate from " + er.getUrl() + " is trusted.");
handler.proceed();
}catch(Exception e){
Log.d(TAG, "Failed to access " + er.getUrl() + ". Error: " + er.getPrimaryError());
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
String message = "SSL Certificate error.";
switch (er.getPrimaryError()) {
case SslError.SSL_UNTRUSTED:
message = "O certificado não é confiável.";
break;
case SslError.SSL_EXPIRED:
message = "O certificado expirou.";
break;
case SslError.SSL_IDMISMATCH:
message = "Hostname inválido para o certificado.";
break;
case SslError.SSL_NOTYETVALID:
message = "O certificado é inválido.";
break;
}
message += " Deseja continuar mesmo assim?";
builder.setTitle("Erro");
builder.setMessage(message);
builder.setPositiveButton("Sim", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
handler.proceed();
}
});
builder.setNegativeButton("Não", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
handler.cancel();
}
});
final AlertDialog dialog = builder.create();
dialog.show();
}
}
}https://stackoverflow.com/questions/36050741
复制相似问题