返回

深层解析 Android 9.0 中的 net::ERR_CLEARTEXT_NOT_PERMITTED 错误

Android

Android 9.0 中 WebView 的 net::ERR_CLEARTEXT_NOT_PERMITTED 错误:揭秘并解决

理解 net::ERR_CLEARTEXT_NOT_PERMITTED 错误

在 Android 9.0(又称 Pie)中,WebView 开发人员可能会遭遇令人头疼的 net::ERR_CLEARTEXT_NOT_PERMITTED 错误。它表明 WebView 无法加载特定的 URL,原因是 "HTTP 响应中没有有效的 HTTPS 证书"。深入了解此错误的本质至关重要,以便制定清晰的解决方案。

HTTP、HTTPS 和 Cleartext

错误的根源在于对 HTTP、HTTPS 和 cleartext 的理解。HTTP(超文本传输协议)和 HTTPS(超文本传输安全协议)是用于网络数据传输的两种协议。HTTPS 是 HTTP 的安全版本,利用 TLS(传输层安全性)加密来保护数据。

Cleartext 顾名思义,表示未加密的数据。在 WebView 上下文中,cleartext 指的是通过 HTTP(而非 HTTPS)传输的数据。

Android 9.0 WebView 安全增强

Android 9.0 中,Google 提升了 WebView 的安全性,默认情况下禁止加载通过 HTTP(cleartext)传输的数据。这旨在加强用户数据保护,防范网络攻击。

错误成因

net::ERR_CLEARTEXT_NOT_PERMITTED 错误源于 WebView 尝试加载通过 HTTP 传输的 URL。由于 Android 9.0 中的 WebView 不再加载 cleartext 数据,因此触发此错误。

解决方案:HTTPS 至上

理想的解决方案是确保所有要加载到 WebView 中的 URL 都使用 HTTPS。有两种方法可以实现这一点:

  1. 确保服务器配置为通过 HTTPS 提供内容。
  2. 使用重定向将 HTTP URL 转到对应的 HTTPS URL。

解决方案:拦截 Cleartext 请求

对于无法切换到 HTTPS 的 URL,开发者可以使用 WebViewClient.shouldInterceptRequest() 方法来拦截 cleartext 请求并手动加载它们。这个方法让开发者可以决定是否允许 WebView 加载请求,代码如下:

@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
    if (request.getUrl().toString().startsWith("http://")) {
        // 手动加载 cleartext 请求
        return new WebResourceResponse("text/html", "UTF-8", null);
    } else {
        // 允许 WebView 加载 HTTPS 请求
        return super.shouldInterceptRequest(view, request);
    }
}

注意: 此方法仅适用于无法使用 HTTPS 的特殊情况。强烈建议将所有 URL 迁移到 HTTPS。

结论

net::ERR_CLEARTEXT_NOT_PERMITTED 错误是 Android 9.0 WebView 安全增强的一部分。通过采用 HTTPS 或使用 WebViewClient.shouldInterceptRequest() 方法,开发者可以轻松解决此问题,确保应用符合 Android 9.0 的安全要求。HTTPS 的普及和拦截 cleartext 请求的谨慎使用将带来更安全的 WebView 体验。

常见问题解答

  1. 为什么 Android 9.0 中 WebView 不再加载 cleartext 数据?
    为了提高用户数据安全性,防止网络攻击。

  2. 我必须将所有 URL 迁移到 HTTPS 吗?
    优先推荐将所有 URL 迁移到 HTTPS。

  3. WebViewClient.shouldInterceptRequest() 方法适用于哪些情况?
    在无法使用 HTTPS 的特殊情况下,可以拦截 cleartext 请求并手动加载它们。

  4. 我应该始终允许 WebView 加载 cleartext 请求吗?
    不建议。应仅在确实无法使用 HTTPS 时使用此方法。

  5. 还有什么方法可以解决此错误吗?
    没有其他推荐的方法。HTTPS 和 WebViewClient.shouldInterceptRequest() 方法是官方推荐的解决方案。