在非常有限的情况下允许来自Android App的明文HTTP流量

我已阅读
Android 8: Cleartext HTTP traffic not permitted,但没有一个答案似乎允许我做我想要的.

我有一个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)?

最佳答案 如果您使用的是
OkHttp,则可以构建一个客户端:

OkHttpClient client = new OkHttpClient.Builder() 
.connectionSpecs(Arrays.asList(ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS))
.build();

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

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

OkHttpClient client = new OkHttpClient.Builder().build()

当你想使用明文连接时.

编辑:使用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();
}
点赞