【问题标题】:Android WebView handle onReceivedClientCertRequestAndroid WebView 处理 onReceivedClientCertRequest
【发布时间】:2016-05-10 04:20:55
【问题描述】:

我正在开发一个在 WebView 中使用客户端证书身份验证的 Android 应用程序。证书 (cert.pfx) 和密码嵌入在应用程序中。

在 WebView 中使用 ajax 调用执行客户端证书身份验证请求时,会调用以下函数:

@Override
public void onReceivedClientCertRequest(WebView view, final ClientCertRequest request) {}

据我所知,我需要打电话:

request.proceed(PrivateKey privateKey, X509Certificate[] chain)

知道如何从嵌入式证书创建 PrivateKey 和 X509Certificate 对象以继续处理请求。 顺便说一句,这是在 Android 应用程序上实施客户端证书身份验证的正确方法吗?如果没有,请指教。

【问题讨论】:

    标签: android ssl webview client-certificates


    【解决方案1】:

    解决了使用 KeyStore 获取 PrivateKey 和 X509Certificate 对象:

        private X509Certificate[] mCertificates;
        private PrivateKey mPrivateKey;
    
        private void loadCertificateAndPrivateKey() {
              try {
                    InputStream certificateFileStream = getClass().getResourceAsStream("/assets/cert.pfx");
    
                    KeyStore keyStore = KeyStore.getInstance("PKCS12");
                    String password = "password";
                    keyStore.load(certificateFileStream, password != null ? password.toCharArray() : null);
    
                    Enumeration<String> aliases = keyStore.aliases();
                    String alias = aliases.nextElement();
    
                    Key key = keyStore.getKey(alias, password.toCharArray());
                    if (key instanceof PrivateKey) {
                        mPrivateKey = (PrivateKey)key;
                        Certificate cert = keyStore.getCertificate(alias);
                        mCertificates = new X509Certificate[1];
                        mCertificates[0] = (X509Certificate)cert;
                     }
    
                     certificateFileStream.close();
    
                } catch (Exception e) {
                     Log.e(TAG, e.getMessage());
             }
        }
    
    
        private WebViewClient mWebViewClient = new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return false;
            }
    
            @Override
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                handler.proceed();
            }
    
            @Override
            public void onReceivedClientCertRequest(WebView view, final ClientCertRequest request) {
                if (mCertificates == null || mPrivateKey == null) {
                    loadCertificateAndPrivateKey();
                } 
                request.proceed(mPrivateKey, mCertificates);
            }
        };
    

    【讨论】:

    • 我们是否需要提供这个 /assets/cert.pfx 或者它会默认选择
    【解决方案2】:

    我遇到了同样的问题,我是这样解决的:

    private void initPrivateKeyAndX509Certificate(int clientCertResourceId, String clientCertPassword) throws UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException {
            try {
                InputStream certificateFileStream = null;
                if (clientCertResourceId > 0) {
                    certificateFileStream = new ByteArrayInputStream(Utility.readbyteFromResources(clientCertResourceId, MYApplication.getAppContext()));
                }
    
                if (certificateFileStream != null) {
                    KeyStore keyStore = KeyStore.getInstance("PKCS12");
                    keyStore.load(certificateFileStream, clientCertPassword != null ? clientCertPassword.toCharArray() : null);
    
                    Enumeration<String> aliases = keyStore.aliases();
    
                    while (aliases.hasMoreElements()) {
                        String alias = aliases.nextElement();
                        Key key = keyStore.getKey(alias, clientCertPassword.toCharArray());
                        if (key instanceof PrivateKey) {
                            mPrivateKey = (PrivateKey) key;
                            Certificate[] arrayOfCertificate = keyStore.getCertificateChain(alias);
                            mCertificates = new X509Certificate[arrayOfCertificate.length];
                            for (int i = 0; i < mCertificates.length; i++) {
                                mCertificates[i] = ((X509Certificate) arrayOfCertificate[i]);
                            }
                            break;
                        }
                    }
    
                    certificateFileStream.close();
                }
    
            } catch (Exception e) {
                Log.e(TAG, e.getMessage());
                throw e;
            }
        }
    

    其中 clientCertResourceId 是 raw 文件夹中 p12 相关的 resourceId。 然后我以这种方式覆盖了 onReveicedClientCertRequest:

    @Override
        public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) {
            if (mPrivateKey != null && mCertificates != null && mCertificates.length != 0) {
                request.proceed(mPrivateKey, mCertificates);
            } else {
                request.cancel();
            }
        }
    

    我想知道这种方式是否正确,但目前可行

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-03
      • 2021-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多