是否可以基于访问https URL的webview创建Android应用程序
我有一个类正在使用webview打开这个url:我已经使用下面的代码创建了本地证书。我成功地得到了200的响应,但我的问题是如何继续向用户显示网页。 我已经测试了这段代码:是否可以基于访问https URL的webview创建Android应用程序,https,android-webview,x509certificate,httpsurlconnection,sslsocketfactory,Https,Android Webview,X509certificate,Httpsurlconnection,Sslsocketfactory,我有一个类正在使用webview打开这个url:我已经使用下面的代码创建了本地证书。我成功地得到了200的响应,但我的问题是如何继续向用户显示网页。 我已经测试了这段代码: public class WebViewFragment extends Fragment { public final String TAG = WebViewFragment.class.getSimpleName(); private WebView webView; public stat
public class WebViewFragment extends Fragment {
public final String TAG = WebViewFragment.class.getSimpleName();
private WebView webView;
public static final int DEFAULT_BUFFER_SIZE = 2048;
public static final String DEFAULT_CHARSET_NAME = "UTF-8";
public WebViewFragment() {
}
public static WebViewFragment newInstance() {
return new WebViewFragment();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.layout_webview_fragment, container, false);
initGlobal(view);
return view;
}
private void initGlobal(View view) {
webView = (WebView) view.findViewById(R.id.webview);
//MyBrowser is a custom class which extends Webviewclient which loads the given url in the webview
webView.setWebViewClient(new MyBrowser());
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
// webView.loadUrl("http://www.google.com");
// webView.loadUrl("https://www.github.com");
// webView.loadUrl("https://eaadhaar.uidai.gov.in/");
try {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = new BufferedInputStream(getActivity().getResources().openRawResource(R.raw.newcertificate));
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Create a SSLContext with the certificate
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
// Create a HTTPS connection
URL url = new URL("https://eaadhaar.uidai.gov.in");
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(sslContext.getSocketFactory());
InputStream in = conn.getInputStream();
int lastResponseCode = conn.getResponseCode();
Log.e(TAG, "response code=" + lastResponseCode);
if (lastResponseCode == 200) {
Toast.makeText(getActivity(), "Response code==" + lastResponseCode, Toast.LENGTH_SHORT).show();
}
copyInputStreamToOutputStream(in, System.out, 2048, true, true);
} catch (Exception e) {
Log.e(TAG, "Exception========" + e.toString());
}
}
public void copyInputStreamToOutputStream(InputStream from, OutputStream to, int bufferSize, boolean closeInput, boolean closeOutput) {
try {
int totalBytesRead = 0;
int bytesRead = 0;
int offset = 0;
byte[] data = new byte[bufferSize];
while ((bytesRead = from.read(data, offset, bufferSize)) > 0) {
totalBytesRead += bytesRead;
to.write(data, offset, bytesRead);
Log.e(TAG, "Copied " + totalBytesRead + " bytes");
}
closeStreams(from, to, closeInput, closeOutput);
} catch (Exception e) {
closeStreams(from, to, closeInput, closeOutput);
e.printStackTrace();
throw new RuntimeException(e);
}
}
public void closeStreams(InputStream from, OutputStream to, boolean closeInput, boolean closeOutput) {
try {
if (to != null)
to.flush();
} catch (Exception e) {
e.printStackTrace();
}
try {
if (closeInput && from != null)
from.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
if (closeOutput && to != null)
to.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
问题很可能是服务器没有发送完整的证书链(不发送中间证书) 请看这里: 单击
认证路径
,您将看到GeoTrust SSL CA-G3
旁边的额外下载
这是一个WebView特有的东西:它不获取中间证书(像Chrome或Firefox这样的常规浏览器要么这样做,要么缓存用户在浏览其他页面时看到的证书)
您需要联系服务器管理员/ops以发送所有中介证书。
我们的应用程序也有类似的问题,通过在SSL握手中发送所有中间证书,问题得到了解决
覆盖OnReceivedSlerror是解决问题的不安全方法,不应在生产应用程序中使用。将其视为仅用于开发的工具。问题很可能是服务器没有发送完整的证书链(不发送中间证书) 请看这里: 单击
认证路径
,您将看到GeoTrust SSL CA-G3
旁边的额外下载
这是一个WebView特有的东西:它不获取中间证书(像Chrome或Firefox这样的常规浏览器要么这样做,要么缓存用户在浏览其他页面时看到的证书)
您需要联系服务器管理员/ops以发送所有中介证书。
我们的应用程序也有类似的问题,通过在SSL握手中发送所有中间证书,问题得到了解决
覆盖OnReceivedSlerror是解决问题的不安全方法,不应在生产应用程序中使用。将其视为仅用于开发的工具。您的确切问题是什么?是“如何在UI中显示webview”还是“webview是否可以加载HTTPS”或“webview是否可以加载证书不受操作系统信任且我希望它使用自定义CA存储验证证书的HTTPS页面”?@jakub.g实际上,我只想在webview中加载上面的url,并显示空白屏幕。我找到的任何方法都必须使用OnReceivedSlerror方法来绕过此问题。我被误导了,我需要自定义密钥库来访问url。如果显示空白屏幕,这意味着很可能由于某种原因无法验证https证书。请注意,您不应该在生产应用程序中只执行
onReceivedSslError
中的handler.procedure()
,因为这会破坏HTTPS的用途,因为它会使应用程序容易受到中间人攻击。@jakub.g但我不会调用任何HTTPS web服务,只需打开url,向用户显示一个对话框,提醒用户是否希望继续。如果我遵循此操作,我的应用程序将被拒绝?我只在StackOverflow上得到了这个解决方案,如果您显示对话框,这比盲目接受无效证书要好。但是https证书验证仍然由于某些原因失败:1)设备没有正确的CA证书,或者2)您的证书无效(可能是自签名等)。在像Chrome这样的普通浏览器中,页面加载正常吗?如果是这样,最有可能的问题是服务器没有发送完整的证书链。你的确切问题是什么?是“如何在UI中显示webview”还是“webview是否可以加载HTTPS”或“webview是否可以加载证书不受操作系统信任且我希望它使用自定义CA存储验证证书的HTTPS页面”?@jakub.g实际上,我只想在webview中加载上面的url,并显示空白屏幕。我找到的任何方法都必须使用OnReceivedSlerror方法来绕过此问题。我被误导了,我需要自定义密钥库来访问url。如果显示空白屏幕,这意味着很可能由于某种原因无法验证https证书。请注意,您不应该在生产应用程序中只执行onReceivedSslError
中的handler.procedure()
,因为这会破坏HTTPS的用途,因为它会使应用程序容易受到中间人攻击。@jakub.g但我不会调用任何HTTPS web服务,只需打开url,向用户显示一个对话框,提醒用户是否希望继续。如果我遵循此操作,我的应用程序将被拒绝?我只在StackOverflow上得到了这个解决方案,如果您显示对话框,这比盲目接受无效证书要好。但是https证书验证仍然由于某些原因失败:1)设备没有正确的CA证书,或者2)您的证书无效(可能是自签名等)。在像Chrome这样的普通浏览器中,页面加载正常吗?如果是这样,最有可能的问题是服务器没有发送完整的证书链。