在非常有限的情况下允许来自 Android 应用程序的明文 HTTP 流量

Mar*_*ica 5 android

我已阅读Android 8: Cleartext HTTP traffic not allowed,但似乎没有任何答案允许我做我想做的事。

我有一个 Android 应用程序,其中另一个客户端可以使用证书来标识自己。应用程序想要验证该证书。验证证书的一部分是从证书颁发者处获取证书吊销列表 (CRL)。CRL 的分发点在证书中列出,并且不可避免地是一个 HTTP URL(CRL 本身由颁发者签名,因此不存在安全问题,如果它是 HTTPS URL,人们会想要验证保护 CRL 分发点的证书,并检查它是否已被吊销...)

可能的解决方案,以及为什么它们对我不起作用:

  • 别担心 - 让 TLS 库担心验证证书。不幸的是,两个客户端之间没有直接的 TLS 连接;它是通过一个服务器的所有介导的(其由TLS连接到)。
  • 创建network_security_config.xml列出允许 HTTP 访问的域。遗憾的是,我在构建应用程序时不知道 URL - 这取决于 CA 决定放入其证书的内容。
  • 放入android:usesCleartextTraffic="true"清单。这意味着任何流量都可以是 HTTP,如果可能的话,我宁愿避免这种情况。(例如,与服务器的通信绝对必须是HTTPS,如果我不小心使用HTTP,我会出错。)

代码有什么办法可以说“允许连接为 HTTP”(但仅默认为 HTTPS)?

qua*_*rse 1

如果您使用OkHttp,您可以这样构建客户端:

OkHttpClient client = new OkHttpClient.Builder() 
.connectionSpecs(Arrays.asList(ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS))
.build();
Run Code Online (Sandbox Code Playgroud)

这将只允许通过 HTTPS 进行连接。那么,您可以使用第三个选项 ( android:usesCleartextTraffic="true"),当您通过此客户端建立明文连接时,它将失败。

最后,您可以创建一个标准的 OkHttp 客户端:

OkHttpClient client = new OkHttpClient.Builder().build()
Run Code Online (Sandbox Code Playgroud)

当您想使用明文连接时。

编辑:使用HttpUrlConnection,您可以简单地检查返回的连接是否是HttpsUrlConnection,例如:

try {
    URL my_url = new URL(path);
    HttpUrlConnection urlConnection = (HttpURLConnection) my_url.openConnection();
    if(!(urlConnection instanceof HttpsURLConnection)) {
        // cleartext connection, throw error
        throw new NotHttpsException();
    }
    // the connection is secure, do normal stuff here
    urlConnection.setRequestMethod("POST");
    urlConnection.setConnectTimeout(1500);
    urlConnection.setReadTimeout(1500);
    result = IOUtil.readFully(urlConnection.getInputStream());
} catch(Exception e) {
    e.printStackTrace()
} finally {
    if(urlConnection != null) urlConnection.disconnect();
}
Run Code Online (Sandbox Code Playgroud)