我有webview
加载网址,但无法正常工作。
看看我的代码:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView wv = (WebView) findViewById(R.id.webView);
//Log.d("rudyy", "aqui");
wv.loadUrl("https://tripulanteaims.tam.com.br/wtouch/wtouch.exe/index");
//Log.d("rudyy", "fim");
}
}
执行此代码时,android返回此错误:
Failed to validate the certificate chain, error: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
请帮助我。
答案 0 :(得分:47)
创建WebViewClient:
private class WvClient extends WebViewClient
{
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError er) {
handler.proceed();
// Ignore SSL certificate errors
}
}
并将初始化的WebViewClient(“WvClient”)设置为WebView(在这种情况下为“wv”):
wv.setWebViewClient(new WvClient());
或在一行中:
wv.setWebViewClient(new WebViewClient() {@Override public void onReceivedSslError(WebView v, SslErrorHandler handler, SslError er){ handler.proceed(); }});
答案 1 :(得分:9)
我正在处理这个问题并且非常坦率地允许MITM攻击是禁止的。这是一个支持固定的更清洁的解决方案。将证书保存到原始资源文件夹中 注意:遗憾的是,当您调用getCertificate()时,SSLError会向我们提供SslCertificate。 SslCertificate有点无用。它的公共API不允许您验证公钥,只发布创建日期,过期日期,发布日期。但是,如果打开此类,您将看到未公开的X509Certificate成员变量。 IDK为何做出这一设计决定。但是有一个用于获取Bundle的API,并且X509证书成员变量存储在那里。因此我们以这种方式访问它,因为证书上有更多有用的方法。
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
SslCertificate sslCertificateServer = error.getCertificate();
Certificate pinnedCert = getCertificateForRawResource(R.raw.your_cert, mContext);
Certificate serverCert = convertSSLCertificateToCertificate(sslCertificateServer);
if(pinnedCert.equals(serverCert)) {
handler.proceed();
} else {
super.onReceivedSslError(view, handler, error);
}
}
public static Certificate getCertificateForRawResource(int resourceId, Context context) {
CertificateFactory cf = null;
Certificate ca = null;
Resources resources = context.getResources();
InputStream caInput = resources.openRawResource(resourceId);
try {
cf = CertificateFactory.getInstance("X.509");
ca = cf.generateCertificate(caInput);
} catch (CertificateException e) {
Log.e(TAG, "exception", e);
} finally {
try {
caInput.close();
} catch (IOException e) {
Log.e(TAG, "exception", e);
}
}
return ca;
}
public static Certificate convertSSLCertificateToCertificate(SslCertificate sslCertificate) {
CertificateFactory cf = null;
Certificate certificate = null;
Bundle bundle = sslCertificate.saveState(sslCertificate);
byte[] bytes = bundle.getByteArray("x509-certificate");
if (bytes != null) {
try {
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
Certificate cert = certFactory.generateCertificate(new ByteArrayInputStream(bytes));
certificate = cert;
} catch (CertificateException e) {
Log.e(TAG, "exception", e);
}
}
return certificate;
}
答案 2 :(得分:0)
这是正确的解决方案,Google会通过实施以下代码来批准您的应用:
@Override
public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {
// for SSLErrorHandler
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
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();
}
如果您使用以下代码,则在调试时可以使用,但Google会拒绝您的应用:
private class WvClient extends WebViewClient
{
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError er) {
handler.proceed();
// Ignore SSL certificate errors
}
}