web-dev-qa-db-ja.com

Android WebViewClientで特定のSSLプロトコルを有効にする

私のアプリケーションは、WebViewClientを使用してサーバーへのSSL接続を確立します。サーバーは、TLSv1.1以上のプロトコルのみを受け入れるように構成されています。

1)どのSSLプロトコルがa)サポートされているか、b)デバイスでAndroid WebViewClientを使用しているときにデフォルトで有効にされているかを確認するにはどうすればよいですか。
2)Androidアプリケーションで使用されるWebViewClientインスタンスに対して特定のSSLプロトコルを有効にする方法を教えてください。

Android 4.3を実行しているテストデバイスの1つで、WebViewClientは「SSLハンドシェイクの実行に失敗しました」という説明とともにonReceivedErrorコールバックをスローします
Chromeログは次のとおりです。
01-29 15:58:00.073 5486 5525 Wクロム_ネット:external/chromium/net/http/http_stream_factory_impl_job.cc:865:[0129/155800:WARNING:http_stream_factory_impl_job.cc(865)] SSLv3にフォールバックホストがTLSに耐性がないため:10.209.126.125:443 01-29 15:58:00.083 5486 5525 E chroma_net:external/chromium/net/socket/ssl_client_socket_openssl.cc:792:[0129/155800:ERROR:ssl_client_socket_openssl.cc(792 )]ハンドシェイクに失敗しました。 0、SSLエラーコード5、net_error -107を返しました

また、私のアプリケーションはHttpClientクラスとHttpsUrlConnectionクラスを使用してSSL接続をセットアップします。これらのクラスを使用するときにSSLSocket APIを使用して特定のプロトコルを有効にすることができました。 http://developer.Android.com/reference/javax/net/ssl/SSLSocket.html#setEnabledProtocols(Java.lang.String [])

WebViewClientでも同じことをする必要があります。

26
user802467

文書によると、Android <4.3。でWebViewのTLS 1.0をサポートすることはできません。Android 4.4ではデフォルトで無効になっています。

さまざまなブラウザーでのTLS 1.0のサポートについては、このチャートを確認してください。 https://en.wikipedia.org/wiki/Transport_Layer_Security#Web_browsers

9
M. C.

アプリでGoogle Play開発者サービスを使用している場合、または使用する意思がある場合は、Providerをインストールすることにより、古い携帯電話で新しいセキュリティ機能を使用できます。インストールは簡単で、1行だけです(さらに例外処理など)。また、まだ持っていない場合は、Google Playサービスをgradleファイルに追加する必要があります。 ProviderInstaller-baseパッケージに含まれています。

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

完全な例については、 「SSLエクスプロイトから保護するためのセキュリティプロバイダーの更新」 Googleをご覧ください。

2
iagreen

実際、私はそれを機能させることができましたが、そのためには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);

また、従来のトラストマネージャーマニピュレーター、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();
        }
    }
}
2
Alex

Android 4.3はTSL 1.1をサポートしていないため、TSL1.0のみがこの記事を読みます https://www.ssllabs.com/ssltest/clients.html find Android 4.3が表示されます

プロトコルTLS 1.3 TLS 1.2なしTLS 1.1なしTLS 1.1なしTLS 1.0なしSSL 3 INSECUREありSSL 2なし

0
lemon