使用Android WebViewClient启用特定的SSL协议

我的应用程序使用WebViewClient与服务器build立SSL连接。 服务器被configuration为只接受TLSv1.1及以上协议。

1)如何检查哪些SSL协议是a)支持和b)在设备上使用Android WebViewClient时默认启用。
2)如何为我的应用程序中使用的Android WebViewClient实例启用特定的SSL协议。

在运行Android 4.3的testing设备之一上,WebViewClient抛出onReceivedErrorcallback,描述为“执行SSL握手失败”
Chrome日志如下:
01-29 15:58:00.073 5486 5525 W chromium_net:external / chromium / net / http / http_stream_factory_impl_job.cc:865:[0129/155800:警告:http_stream_factory_impl_job.cc(865)]回退到SSLv3,因为主机是TLS不能容忍的:10.209.126.125:443 01-29 15:58:00.083 5486 5525 E chromium_net:external / chromium / net / socket / ssl_client_socket_openssl.cc:792:[0129/155800:ERROR:ssl_client_socket_openssl.cc(792)] handshake failed; 返回0,SSL错误代码5,net_error -107

我的应用程序也使用HttpClient和HttpsUrlConnection类来build立SSL连接。 在使用这些类时,我能够使用SSLSocket API来启用特定的协议。 http://developer.android.com/reference/javax/net/ssl/SSLSocket.html#setEnabledProtocols(java.lang.String中[])

我需要对WebViewClient执行相同的操作。

Related of "使用Android WebViewClient启用特定的SSL协议"

根据文档,不可能在Android 4.3中的WebView中支持TLS 1.0。 对于Android 4.4,它默认是禁用的。

在不同浏览器中查看此图表以获取对TLS 1.0的支持: https : //en.wikipedia.org/wiki/Transport_Layer_Security#Web_browsers

如果您的应用程序正在使用,或者您愿意使用Google Play服务,则可以通过安装Provider在较旧的电话上使用较新的安全function。 它很容易安装,只有一行(加上exception处理等)。 如果您尚未拥有Google Play服务,则还需要将其添加到您的Gradle文件中。 ProviderInstaller包含在-base包中。

 try { ProviderInstaller.installIfNeeded(this); } catch (GooglePlayServicesRepairableException e) { // Fix it } catch (GooglePlayServicesNotAvailableException e) { // Skip it } 

有关完整示例,请参阅Google的“更新您的安全提供程序以防范SSL漏洞” 。

其实,我设法使它工作,但你需要okHttp库。 当你设置浏览器活动时试试这个:

  WebViewClient client = new WebViewClient() { private OkHttpClient okHttp = new OkHttpClient.Builder().build(); @Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) { Request okHttpRequest = new Request.Builder().url(url).build(); try { Response response = okHttp.newCall(okHttpRequest).execute(); return new WebResourceResponse(response.header("Content-Type", "plain/text"), response.header("Content-Encoding", "deflate"), response.body().byteStream()); } catch (IOException e) { e.printStackTrace(); } return null; } }; webView.setWebViewClient(client); 

另外,您还需要经典的信任pipe理器操作器,SSL套接字工厂及其在您的应用程序类中的实现:

 public class TrustManagerManipulator implements X509TrustManager { private static TrustManager[] trustManagers; private static final X509Certificate[] acceptedIssuers = new X509Certificate[] {}; public boolean isClientTrusted(X509Certificate[] chain) { return true; } public boolean isServerTrusted(X509Certificate[] chain) { return true; } public static void allowAllSSL() { HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }); SSLContext context = null; if (trustManagers == null) { trustManagers = new TrustManager[] { new TrustManagerManipulator() }; } try { context = SSLContext.getInstance("TLS"); context.init(null, trustManagers, new SecureRandom()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (KeyManagementException e) { e.printStackTrace(); } HttpsURLConnection.setDefaultSSLSocketFactory(context .getSocketFactory()); } public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return acceptedIssuers; } } 

SSlsockets工厂:

 public class TLSSocketFactory extends SSLSocketFactory { private SSLSocketFactory internalSSLSocketFactory; public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException { SSLContext context = SSLContext.getInstance("TLS"); TrustManager[] managers = new TrustManager[] { new TrustManagerManipulator() }; context.init(null, managers, new SecureRandom()); internalSSLSocketFactory = context.getSocketFactory(); } @Override public String[] getDefaultCipherSuites() { return internalSSLSocketFactory.getDefaultCipherSuites(); } @Override public String[] getSupportedCipherSuites() { return internalSSLSocketFactory.getSupportedCipherSuites(); } @Override public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose)); } @Override public Socket createSocket(String host, int port) throws IOException, UnknownHostException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port)); } @Override public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort)); } @Override public Socket createSocket(InetAddress host, int port) throws IOException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port)); } @Override public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort)); } private Socket enableTLSOnSocket(Socket socket) { if(socket != null && (socket instanceof SSLSocket)) { ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"}); } return socket; } } 

应用程序类:

 public class App extends Application { private static App appInstance; @Override public void onCreate() { super.onCreate(); setupSSLconnections(); } private void setupSSLconnections() { try { HttpsURLConnection.setDefaultSSLSocketFactory(new TLSSocketFactory()); } catch (KeyManagementException | NoSuchAlgorithmException e) { e.printStackTrace(); } } }