应用上架GooglePlay 收到邮件提示 For more information on how to address WebView SSL Error Handler alerts, please see this Google Help Center article.
出现这个原因是因为我在app中使用webview加载Https的H5界面,在onReceivedSslError()中处理SslErrorHandler时,出现白屏现象,原因是webview默认在加载有证书验证的url时,会默认使用handler.cancel()进行拦截操作,这里只需要改成handler.proceed()就可以解决白屏问题了。
但是,apk上传GooglePlay时会检测到“这种实施方式会忽略所有 SSL 证书验证错误,使应用容易受到中间人攻击。攻击者可能会更改受影响的 WebView 内容、读取传输的数据(例如登录凭据),以及执行应用中使用 JavaScript 的代码”(详情请点击进入https://support.google.com/faqs/answer/7071387)
解决方案:
1、检测到异常时,弹出提示框,提示用户(本人没有亲测是否可以上传GooglePlay)
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
final SslErrorHandler mHandler ;
mHandler= handler;
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setMessage("ssl证书验证失败");
builder.setPositiveButton("继续", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mHandler.proceed();
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mHandler.cancel();
}
});
builder.setOnKeyListener(new DialogInterface.OnKeyListener() {
@Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
mHandler.cancel();
dialog.dismiss();
return true;
}
return false;
}
});
AlertDialog dialog = builder.create();
dialog.show();
}2、步骤繁杂,亲测可提交GooglePlay。
- 从网站上检索证书(可以参考:https://blog.csdn.net/qq_35229064/article/details/88250392)
- 将证书(.cer文件)复制到应用程序的res / raw文件夹中
在代码中,通过调用LoadSslCertificate()加载证书
private static final int[] CERTIFICATES = {
R.raw.证书名, // you can put several certificates
};
private ArrayList<SslCertificate> certificates = new ArrayList<>();
private void loadSSLCertificates() {
try {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
for (int rawId : CERTIFICATES) {
InputStream inputStream = getResources().openRawResource(rawId);
InputStream certificateInput = new BufferedInputStream(inputStream);
try {
Certificate certificate = certificateFactory.generateCertificate(certificateInput);
if (certificate instanceof X509Certificate) {
X509Certificate x509Certificate = (X509Certificate) certificate;
SslCertificate sslCertificate = new SslCertificate(x509Certificate);
certificates.add(sslCertificate);
} else {
Log.w(TAG, "Wrong Certificate format: " + rawId);
}
} catch (CertificateException exception) {
Log.w(TAG, "Cannot read certificate: " + rawId);
} finally {
try {
certificateInput.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
} catch (CertificateException e) {
e.printStackTrace();
}
}发生SslError时,请检查服务器证书是否与一个嵌入式证书匹配。请注意,无法直接比较证书,因此我使用SslCertificate.saveState将证书数据放入Bundle,然后我比较所有bundle条目
webView.setWebViewClient(new WebViewClient() {
@Override
public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {
// Checks Embedded certificates
SslCertificate serverCertificate = error.getCertificate();
Bundle serverBundle = SslCertificate.saveState(serverCertificate);
for (SslCertificate appCertificate : certificates) {
if (TextUtils.equals(serverCertificate.toString(), appCertificate.toString())) { // First fast check
Bundle appBundle = SslCertificate.saveState(appCertificate);
Set<String> keySet = appBundle.keySet();
boolean matches = true;
for (String key : keySet) {
Object serverObj = serverBundle.get(key);
Object appObj = appBundle.get(key);
if (serverObj instanceof byte[] && appObj instanceof byte[]) { // key "x509-certificate"
if (!Arrays.equals((byte[]) serverObj, (byte[]) appObj)) {
matches = false;
break;
}
} else if ((serverObj != null) && !serverObj.equals(appObj)) {
matches = false;
break;
}
}
if (matches) {
handler.proceed();
return;
}
}
}
handler.cancel();
String message = "SSL Error " + error.getPrimaryError();
Log.w(TAG, message);
}
});然后就可以测试结果了
(网上搜索加自己理解,请大家多多指点)
版权声明:本文为qq_35229064原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。