Android Webview 使用自签名证书

Android Webview use self-signed certificate

public class NewSSLSocketFactory extends SSLSocketFactory {
    private SSLContext sslContext=SSLContext.getInstance("TLS");  
    private KeyStore setCert(){
        String skuCertBin ="-----BEGIN CERTIFICATE-----\n"+
                                             "SOMETHING TEXT HERE"+
                                      "-----END CERTIFICATE-----";  
        KeyStore trustStore=null;  
        try {
            ByteArrayInputStream derInputStream = new ByteArrayInputStream(skuCertBin.getBytes());  
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");  
            X509Certificate cert = (X509Certificate) certificateFactory.generateCertificate(derInputStream);  
            String alias = cert.getSubjectX500Principal().getName();  
            trustStore = KeyStore.getInstance(KeyStore.getDefaultType());  
            trustStore.load(null, null);  
            trustStore.setCertificateEntry(alias, cert);
        } catch (CertificateException e) {
            e.printStackTrace();  
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();  
        } catch (KeyStoreException e) {
            e.printStackTrace();  
        } catch (IOException e) {
            e.printStackTrace();  
        }
        return trustStore;  
    }
    public NewSSLSocketFactory() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
        super();  
        KeyStore trustStore = setCert();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");  
        tmf.init(trustStore);  
        sslContext.init(null, tmf.getTrustManagers(), null);
    }
....................
}

我的 SSL 套接字代码

当我使用 Jsoup 解析时,我在上面的代码上应用

但是当使用 WebView 时,View 不只显示网页 "https://"

        WebView webView = (WebView) findViewById(R.id.fullWebView);  
        webView.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url){
                view.loadUrl(url);  
                return true;  
            }
        });  
        webView.getSettings().setJavaScriptEnabled(true);  
        webView.getSettings().setDomStorageEnabled(true);  

        webView.loadUrl(url);  

我找到了 setCertificate 方法,但是 "This method was deprecated in API level 17. Calling this function has no useful effect, and will be ignored in future releases."

如何在 webview 上使用这些自定义证书


final PrivateKey privateKey = newSSLSocketFactory.getPrivateKey();
final X509Certificate[] cert= new X509Certificate[1];
cert[0] = newSSLSocketFactory.getCert();

@Override
public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) {
    Log.d("WebviewCheck","cert Working");
    request.proceed(privateKey, cert);
 }

我在每个 onCreate 和新的 WebViewClient 上都使用了这些代码 但是Android不调用onReceivedClientCertRequest,不显示"WebviewCheck" Log

public static class PlaceholderFragment extends Fragment {
        /**
         * The fragment argument representing the section number for this
         * fragment.
         */
        private static final String ARG_SECTION_NUMBER = "section_number";
        private int section_number_fragment = 0;

        public PlaceholderFragment() {
        }

        private void setFragmentNumber(int n) {
            this.section_number_fragment = n;
        }

        /**
         * Returns a new instance of this fragment for the given section
         * number.
         */
        public static PlaceholderFragment newInstance(int sectionNumber) {
            PlaceholderFragment fragment = new PlaceholderFragment();
            fragment.setFragmentNumber(sectionNumber);
            Bundle args = new Bundle();
            args.putInt(ARG_SECTION_NUMBER, sectionNumber);
            fragment.setArguments(args);
            return fragment;
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            int fragmentFile;
            switch (section_number_fragment) {
                case 1:
                    fragmentFile = R.layout.fragment_left;
                    break;
                case 2:
                    fragmentFile = R.layout.fragment_center;
                    break;
                default:
                    // section_number_fragment == 3
                    fragmentFile = R.layout.fragment_right;
                    break;
            }

            View rootView = inflater.inflate(fragmentFile, container, false);
            if ( section_number_fragment==1) {
                FragmentTransaction transaction = getFragmentManager().beginTransaction();
                if (loginCookies == null) {
                    transaction.replace(R.id.leftFragment, new LogoutFragment());
                }
                else
                    transaction.replace(R.id.leftFragment, new LoginFragment());
                transaction.commit();
            }

            if (section_number_fragment != 1 && section_number_fragment != 2) {
                webView = (WebView) rootView.findViewById(R.id.renewWebView);
                webView.setWebViewClient(new WebViewClient() {
                    @Override
                    public boolean shouldOverrideUrlLoading(WebView view, String url){
                        view.loadUrl(url);
                        return true;
                    }
                    @Override
                    public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) {
                        Log.d("WebviewCheck","cert Working");
                        request.proceed(privateKey, cert);
                    }
                    @Override
                    public void onPageStarted(WebView view, String url, Bitmap favicon) {
                        super.onPageStarted(view,url,favicon);
                        if ( url.equals(ManageUrl.circulationPageUrl))
                            webViewFinishChk=false;
                    }
                   @Override
                    public void onPageFinished(WebView view, String url) {
                       super.onPageFinished(view,url);
                       if ( url.equals(ManageUrl.circulationPageUrl))
                           webViewFinishChk=true;
                   }
                });
                webView.setWebChromeClient(new WebChromeClient() {
                    public boolean onJsAlert(WebView view, String url, String message, final android.webkit.JsResult result){
                        new AlertDialog.Builder(view.getContext())
                                .setTitle("AppTitle")
                                .setMessage(message)
                                .setPositiveButton(android.R.string.ok,
                                        new AlertDialog.OnClickListener(){
                                            public void onClick(DialogInterface dialog, int which) {
                                                result.confirm();
                                            }
                                        })
                                .setCancelable(true)
                                .create()
                                .show();

                        return true;
                    }
                    public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
                        new AlertDialog.Builder(view.getContext())
                                .setTitle("AppTitle")
                                .setMessage(message)
                                .setPositiveButton(android.R.string.ok,
                                        new DialogInterface.OnClickListener()
                                        {
                                            public void onClick(DialogInterface dialog, int which)
                                            {
                                                result.confirm();
                                            }
                                        })
                                .setNegativeButton(android.R.string.cancel,
                                        new DialogInterface.OnClickListener()
                                        {
                                            public void onClick(DialogInterface dialog, int which)
                                            {
                                                result.cancel();
                                            }
                                        })
                                .create()
                                .show();

                        return true;
                    }
                });
                webView.getSettings().setJavaScriptEnabled(true);
                webView.getSettings().setDomStorageEnabled(true);

                ListView borrowListView = (ListView) rootView.findViewById(R.id.borrowBookList);
                borrowListView.setAdapter(borrowAdapter);
                /*
                Button refresh = (Button) rootView.findViewById(R.id.refreshBorrowBook);
                refresh.performClick();
                */
            }
            return rootView;
        }
    }

newSSLSocketFactory,privateKey和cert是MainActiviy的私有静态变量,在onCreate方法上初始化

为什么 viewpager 的 webview 仍然没有显示?

String sslCertificate = error.getCertificate().toString();
String mySslCertificate = new SslCertificate(cert).toString();
if ( sslCertificate.equals(mySslCertificate) )
    handler.proceed();

这些代码添加到 WebView onReceivedSslError 方法

我认为这不是一个完美的解决方案。但是这些代码检查了一些 SSL 证书

不显示弹出消息(对话框)