You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android7.1 WebView加载TLS1.3站点出现ERR_SSL_VERSION_OR_CIPHER_MISMATCH问题

解决Android 7.1 WebView加载TLS1.3站点的ERR_SSL_VERSION_OR_CIPHER_MISMATCH错误

问题根源

Android 7.x(API 24-25)系统默认仅支持TLS 1.2,而目标站点使用TLS 1.3。尽管设备上的Chrome浏览器90.0.4430.60本身支持TLS 1.3,但系统WebView并未默认启用该协议支持,导致加载失败。

无需升级浏览器的解决方案

方法1:自定义SSLSocketFactory启用TLS 1.3

通过创建支持TLS 1.3的SSL上下文,替换WebView默认的SSLSocketFactory,让WebView能够与TLS 1.3站点建立连接。

步骤1:实现自定义WebViewClient

import android.net.http.SslError;
import android.webkit.SslErrorHandler;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import java.io.IOException;
import java.net.URL;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class TLS13WebViewClient extends WebViewClient {
    private SSLSocketFactory tls13SocketFactory;
    private ProgressBar spinner;

    public TLS13WebViewClient(ProgressBar spinner) {
        this.spinner = spinner;
        try {
            // 创建支持TLS 1.3的SSL上下文
            SSLContext sslContext = SSLContext.getInstance("TLSv1.3");
            sslContext.init(null, new TrustManager[]{new X509TrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}

                @Override
                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}

                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }
            }}, new SecureRandom());
            tls13SocketFactory = sslContext.getSocketFactory();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
        if (request.getUrl().getProtocol().equals("https")) {
            try {
                HttpsURLConnection connection = (HttpsURLConnection) new URL(request.getUrl().toString()).openConnection();
                // 设置支持TLS 1.3的SSLSocketFactory
                connection.setSSLSocketFactory(tls13SocketFactory);
                // 同时兼容TLS 1.2
                connection.setProtocols(new String[]{"TLSv1.3", "TLSv1.2"});
                return new WebResourceResponse(
                        connection.getContentType(),
                        connection.getContentEncoding(),
                        connection.getInputStream()
                );
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return super.shouldInterceptRequest(view, request);
    }

    @Override
    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
        // 注意:生产环境需移除该行,改为严格的证书校验逻辑,此处仅用于测试
        handler.proceed();
    }

    // 保留原CustomWebViewClient的进度条逻辑
    @Override
    public void onPageStarted(WebView view, String url, android.graphics.Bitmap favicon) {
        super.onPageStarted(view, url, favicon);
        if (spinner != null) {
            spinner.setVisibility(ProgressBar.VISIBLE);
        }
    }

    @Override
    public void onPageFinished(WebView view, String url) {
        super.onPageFinished(view, url);
        if (spinner != null) {
            spinner.setVisibility(ProgressBar.GONE);
        }
    }
}

步骤2:替换原WebViewClient

在Activity代码中替换原客户端:

// 替换原webView.setWebViewClient代码
webView.setWebViewClient(new TLS13WebViewClient(spinner));

方法2:通过反射启用WebView的TLS 1.3支持

针对Chrome 70+版本的WebView(设备Chrome 90符合要求),可通过反射修改WebSettings的协议支持列表:

WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setDomStorageEnabled(true);
settings.setJavaScriptCanOpenWindowsAutomatically(true);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    try {
        // 反射修改WebSettings的启用协议
        Field field = WebSettings.class.getDeclaredField("mWebSettings");
        field.setAccessible(true);
        Object webSettingsImpl = field.get(settings);
        Method method = webSettingsImpl.getClass().getDeclaredMethod("setEnabledProtocols", String[].class);
        method.setAccessible(true);
        method.invoke(webSettingsImpl, new String[]{"TLSv1.3", "TLSv1.2"});
    } catch (Exception e) {
        e.printStackTrace();
    }
}

注意:反射调用存在版本兼容性风险,生产环境优先使用方法1。

关键注意事项

  • 生产环境必须移除onReceivedSslError中的handler.proceed(),实现正确的证书校验,避免安全风险。
  • 两种方法均兼容Android 7.x(API24+)系统,无需调整minSdkVersion。

内容的提问来源于stack exchange,提问作者abhishek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 11:17:52