Java 使用Android WebViewClient启用特定的SSL协议
我的应用程序使用WebViewClient与服务器建立SSL连接。 服务器配置为仅接受TLSv1.1及以上协议 1) 在设备上使用Android WebViewClient时,如何检查默认情况下支持和启用了哪些SSL协议Java 使用Android WebViewClient启用特定的SSL协议,java,android,ssl,https,webviewclient,Java,Android,Ssl,Https,Webviewclient,我的应用程序使用WebViewClient与服务器建立SSL连接。 服务器配置为仅接受TLSv1.1及以上协议 1) 在设备上使用Android WebViewClient时,如何检查默认情况下支持和启用了哪些SSL协议 2) 如何为应用程序中使用的Android WebViewClient实例启用特定的SSL协议 在运行Android 4.3的其中一台测试设备上, WebViewClient引发onReceivedError回调,其描述为“未能执行SSL握手” Chrome日志如下: 01-2
2) 如何为应用程序中使用的Android WebViewClient实例启用特定的SSL协议 在运行Android 4.3的其中一台测试设备上, WebViewClient引发onReceivedError回调,其描述为“未能执行SSL握手”
Chrome日志如下:
01-29 15:58:00.073 5486 5525 W chromium_-net:外部/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:外部/chromium/net/socket/ssl_-client_-socket_-openssl.cc:792:[0129/155800:错误:ssl\u client\u socket\u openssl.cc(792)]握手失败;返回0,ssl错误代码5,网络错误-107 我的应用程序还使用HttpClient和HttpsUrlConnection类来设置SSL连接。
我也需要对WebViewClient执行同样的操作。如果您的应用程序正在使用或愿意使用Google Play服务,您可以通过安装其
提供商
在旧手机上使用更新的安全功能。只需一行即可轻松安装(加上异常处理等)。如果您还没有google play服务,您还需要将其添加到您的gradle文件中。ProviderInstaller
包含在-base
包中
try {
ProviderInstaller.installIfNeeded(this);
} catch (GooglePlayServicesRepairableException e) {
// Fix it
} catch (GooglePlayServicesNotAvailableException e) {
// Skip it
}
有关完整示例,请参阅Google。根据文档说明,在Android<4.3的WebView中不可能支持TLS 1.0。对于Android 4.4,默认情况下禁用TLS 1.0
查看此图表以了解在不同浏览器中对TLS 1.0的支持:实际上,我已设法使其正常工作,但您需要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);
此外,您还需要经典的Trust Manager操纵器、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;
}
}
SSl套接字工厂:
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();
}
}
}
因为安卓4.3不支持TSL1.1,只支持TSL1.0 阅读这篇文章 查找android 4.3将看到 协议 TLS 1.3号 TLS 1.2号 TLS 1.1号 TLS 1.0是 SSL 3不安全是
SSL 2否AFAIK启用的协议WebView不能由应用程序保存。支持或不支持哪些协议取决于Android版本。对于TLS 1.1及更高版本,您需要Android 4.4或更高版本(请参阅)。有人知道这一点吗?我正在做一个项目,目前我们需要从TLS v1.2退到1.1,用于三个非生产测试服务器。我们正在尝试使用类似的东西:adb shell“echo”浏览器--show fps counter--ssl version min=tls1.1--ssl version max=tls1.1”>/data/local/tmp/webview命令行“FPS计数器在Android L平板电脑上显示,但在Android TV上不显示(这很奇怪,因为它们应该是相同的webview代码)。ssl版本标志似乎不起作用;从设备捕获的tcpdump仍然显示正在使用TLS v1.2。任何帮助都会很好。@user802467您找到问题的解决方案了吗?我也面临同样的问题issue@KK_07k11A0585不,我找不到在WebViewClient中配置的方法。我认为上面Robert的评论是正确的。注意:这s是在主线程(UI线程)上调用的同步调用。您可以在后台运行的SyncAdapter或AsyncTask中运行此调用以执行此更新尝试,或使用此调用的installIfNeededAsync版本进行调用以避免阻塞主线程。此外,即使在成功安装提供程序后,您也需要显式启用TLS 1.2/TLS 1.1,同时在[16-20]之间的ndroid版本。我在KITKAT设备上验证了这一点。注意:这似乎无法解决4.1.2客户端的问题。@frank我设法使其工作的最低版本是4.4.2。拦截套接字创建并调用
setEnabledProtocols
似乎是唯一的解决方案。这对任何人都有效吗?我注意到我的4.4设备不再加载LS 1.2服务内容。您的意思是“…支持TLS 1.1”(而不是1.0)?它说默认情况下禁用代码>从4.1到4.4。那么如何启用它呢?不幸的是,我在我的webView中只看到纯文本;这可能取决于javaScript的执行。还发现了这篇文章@ar-g你解决了你的问题吗?如果你解决了,请告诉我。@AlexanderZarovniy问题是在第三方服务中,我们在4.4以下的android上使用不同的方案(与android无关)欢迎这么说。你的回答似乎与OP上的第一条评论基本相同。请参阅以获取指导。