[英]Android Webview Client Certificate, Mutual Auth, SSL over Webview
I have a Webpage which requires Mutual auth to load the page. 我有一个网页,需要Mutual auth加载页面。 I get onReceivedError() with ERROR_FAILED_SSL_HANDSHAKE.
我使用ERROR_FAILED_SSL_HANDSHAKE获得onReceivedError()。 In the logs "Could not establish a secure connection" is printed by Webkit.
在Webkit中打印日志“无法建立安全连接”。 I have searched extensively but could not find an answer.
我已经广泛搜索但找不到答案。 There are several posts but nothing conclusive.
有几个帖子但没有结论。 I tried all 3 solutions posted here .
我在这里发布了所有3个解决方案。 The solution likely to work was :- Solution 1: use ClientCertRequestHandler anyway (It's marked as hidden, but apparently still usable):
可能有效的解决方案是: - 解决方案1:无论如何都使用ClientCertRequestHandler(它被标记为隐藏,但显然仍然可用):
So i modified the android.jar to include the internal API for overriding onReceivedClientCertRequest() But i am not getting the callback at runtime. 所以我修改了android.jar以包含内部API来覆盖onReceivedClientCertRequest()但是我没有在运行时获得回调。 Same is the case with any third party browser.
任何第三方浏览器都是如此。 I tried loading the same webpage in a standard browser.
我尝试在标准浏览器中加载相同的网页。 I got a callback on UI asking the User to select a Client certificate.
我在UI上收到一个回调,要求用户选择一个客户端证书。
So seems that only system browser app can get the callback for onReceivedClientCertRequest() from Webkit. 所以似乎只有系统浏览器应用程序可以从Webkit获取onReceivedClientCertRequest()的回调。
In case of iOS platform, Webview cannot directly load the site too . 对于iOS平台,Webview也无法直接加载网站。 But making an HTTPS Connection using NSURL , keeps the Client certificate in memory for some time and Webview can load this page successfully.
但是使用NSURL进行HTTPS连接会将客户端证书保留在内存中一段时间,并且Webview可以成功加载此页面。
On Android i have successfully setup HTTPS communication by registering an SSLSocketFactory loading Client and Server certificates. 在Android上,我通过注册加载客户端和服务器证书的SSLSocketFactory成功设置了HTTPS通信。 I can do REST API calls using that.However unlike iOS, i cannot find a way in which Android webview can use the Client certificate for Mutual auth.
我可以使用它进行REST API调用。但是,与iOS不同,我找不到Android webview可以使用客户端证书进行Mutual auth的方法。
I think having Mutual auth over a Webview should be supported by the platform as one of the basic requirements for security. 我认为平台应该支持在Webview上进行相互认证,这是安全性的基本要求之一。 Is there any update on this issue ?
这个问题有没有更新?
EDIT 1 : 编辑1 :
I got it working on Android 4.0 to 4.3 as per my answer given below. 根据我在下面给出的答案,我在Android 4.0到4.3上工作了。 Hoverer , now on Android 4.4 , seems that WebViewClientClassicExt class itself is removed.
Hoverer,现在在Android 4.4上,似乎WebViewClientClassicExt类本身被删除了。 Any idea what can be done in this case ?
知道在这种情况下可以做些什么吗? Why is Android not allowing setting ClientCertificates in webview ?
为什么Android不允许在webview中设置ClientCertificates?
So i could get this thing working until 4.3 所以我可以让这件事工作到4.3
I set the Private key and certificates ClientCertRequestHandler proceed() method. 我设置了私钥和证书ClientCertRequestHandler proceed()方法。
Need a fix patch from Android for 4.4 and above 需要Android 4.4及更高版本的修补补丁
EDITED Solutions uptil 4.3 are given below EDITED Solutions uptil 4.3如下
WebviewClientCustom.java WebviewClientCustom.java
public class WebViewClientCustom extends WebViewClient {
private X509Certificate[] certificatesChain;
private PrivateKey clientCertPrivateKey;
private IWebViewCallbacks webviewCallbacks;
public WebViewClientCustom(IWebViewCallbacks webviewCallbacks) {
this.webviewCallbacks = webviewCallbacks;
}
public void onReceivedClientCertRequest(WebView paramWebView,
ClientCertRequestHandler paramClientCertRequestHandler,
String paramString) {
PrivateKey localPrivateKey = this.clientCertPrivateKey;
X509Certificate[] arrayOfX509Certificate = this.certificatesChain;
paramClientCertRequestHandler.proceed(localPrivateKey,
arrayOfX509Certificate);
}
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
webviewCallbacks.onReceivedError( view, errorCode,
description, failingUrl);
super.onReceivedError( view, errorCode,
description, failingUrl);
}
public void setClientCertificate(PrivateKey paramPrivateKey,
X509Certificate[] paramArrayOfX509Certificate) {
this.clientCertPrivateKey = paramPrivateKey;
this.certificatesChain = paramArrayOfX509Certificate;
}
public boolean shouldOverrideUrlLoading(WebView paramWebView,
String paramString) {
return webviewCallbacks.shouldOverrideUrlLoading(paramWebView,
paramString);
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO Auto-generated method stub
webviewCallbacks.onPageStarted(view, url, favicon);
super.onPageStarted(view, url, favicon);
}
@Override
public void onPageFinished(WebView view, String url) {
// TODO Auto-generated method stub
webviewCallbacks.onPageFinished(view, url);
super.onPageFinished(view, url);
}
}
WebViewClientCustomExt.java WebViewClientCustomExt.java
public class WebViewClientCustomExt extends WebViewClientClassicExt {
private X509Certificate[] certificatesChain;
private PrivateKey clientCertPrivateKey;
private IWebViewCallbacks webviewCallbacks;
public WebViewClientCustomExt(IWebViewCallbacks webviewCallbacks) {
this.webviewCallbacks = webviewCallbacks;
}
public void onReceivedClientCertRequest(WebView paramWebView,
ClientCertRequestHandler paramClientCertRequestHandler,
String paramString) {
PrivateKey localPrivateKey = this.clientCertPrivateKey;
X509Certificate[] arrayOfX509Certificate = this.certificatesChain;
paramClientCertRequestHandler.proceed(localPrivateKey,
arrayOfX509Certificate);
}
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
webviewCallbacks.onReceivedError( view, errorCode,
description, failingUrl);
super.onReceivedError( view, errorCode,
description, failingUrl);
}
public void setClientCertificate(PrivateKey paramPrivateKey,
X509Certificate[] paramArrayOfX509Certificate) {
this.clientCertPrivateKey = paramPrivateKey;
this.certificatesChain = paramArrayOfX509Certificate;
}
public boolean shouldOverrideUrlLoading(WebView paramWebView,
String paramString) {
return webviewCallbacks.shouldOverrideUrlLoading(paramWebView, paramString);
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO Auto-generated method stub
webviewCallbacks.onPageStarted(view, url, favicon);
super.onPageStarted(view, url, favicon);
}
@Override
public void onPageFinished(WebView view, String url) {
// TODO Auto-generated method stub
webviewCallbacks.onPageFinished(view, url);
super.onPageFinished(view, url);
}
}
Usage 用法
*/
private void setCertificateData() {
// TODO Auto-generated method stub
try {
KeyStore clientCertKeystore = KeyStore.getInstance("pkcs12");
String clientCertPkcsPassword = getPkcsPassword();
byte[] pkcs12;
pkcs12 = getAuthP12Data();
ByteArrayInputStream pkcs12BAIS = new ByteArrayInputStream(pkcs12);
clientCertKeystore.load(pkcs12BAIS,
clientCertPkcsPassword.toCharArray());
String alias = (clientCertKeystore.aliases().nextElement());
Certificate[] arrayOfCertificate = clientCertKeystore
.getCertificateChain(alias);
X509Certificate[] arrayOfX509Certificate = new X509Certificate[arrayOfCertificate.length];
for (int i = 0; i < arrayOfCertificate.length; i++) {
arrayOfX509Certificate[i] = (X509Certificate) arrayOfCertificate[i];
}
PrivateKey localPrivateKey = (PrivateKey) clientCertKeystore
.getKey(alias, clientCertPkcsPassword.toCharArray());
if (android.os.Build.VERSION.SDK_INT <= 16) {
WebViewClientCustom webvviewClient = new WebViewClientCustom(
myWebViewClient);
webvviewClient.setClientCertificate(localPrivateKey,
arrayOfX509Certificate);
webView.setWebViewClient(webvviewClient);
} else {
WebViewClientCustomExt webvviewClient = new WebViewClientCustomExt(
myWebViewClient);
webvviewClient.setClientCertificate(localPrivateKey,
arrayOfX509Certificate);
webView.setWebViewClient(webvviewClient);
}
// webView.getSettings().setJavaScriptEnabled(true);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.