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

时间:2018-11-22 11:26:25

标签: android

我已经读过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)?

3 个答案:

答案 0 :(得分:1)

NetworkSecurityPolicy.isCleartextTrafficPermitted()上的文档说

  

此标志是基于尽力而为的,因为鉴于提供给它们的访问级别,无法阻止来自Android应用程序的所有明文流量。例如,由于Socket API无法确定其流量是否为明文,因此没有期望set up a simple TCP client API将接受此标志。

因此,这也许是您的一个选择:使用Socket获取CRL。丹尼尔·纽金特(Daniel Nugent)发表了一篇帖子,描述了如何{{3}}

答案 1 :(得分:0)

如果您使用的是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();
}

答案 2 :(得分:0)

该应用与服务器具有TLS连接。
您可以要求服务器向您移交那些CRL URL(首先移交证书,对吗?)。
它甚至可以事先做,并提供证书和CRL。 通过这种方式,您可以获取CRL,而无需松开https锁,也不必创建异常。