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 证书
不显示弹出消息(对话框)
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 证书
不显示弹出消息(对话框)