Android WebView handle onReceivedClientCertRequest

左心房为你撑大大i 提交于 2019-12-03 01:13:18

Solved it using KeyStore to obtain the PrivateKey and X509Certificate objects :

    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);
        }
    };

I encountered the same problem, and I have resolved in this way :

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;
        }
    }

Where the clientCertResourceId is the resourceId related of the p12 which is in raw folder. Then I have overrided the onReveicedClientCertRequest in this way :

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

I wondering if this way to do is the correct one, but currently it works

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!