代码之家  ›  专栏  ›  技术社区  ›  Martin Bonner supports Monica

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

  •  4
  • Martin Bonner supports Monica  · 技术社区  · 6 年前

    我读过 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 回复  |  直到 6 年前
        1
  •  1
  •   qualverse    6 年前

    如果你正在使用 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
  •  1
  •   Bö macht Blau    6 年前

    关于 NetworkSecurityPolicy.isCleartextTrafficPermitted()

    这个标志是在尽力而为的基础上使用的,因为考虑到提供给Android应用程序的访问级别,不可能阻止所有来自Android应用程序的明文通信。例如,没有人期望 Socket API将使用此标志,因为它无法确定其流量是否为明文。

    因此,这可能是您的一个选项:使用 Socket set up a simple TCP client

        3
  •  0
  •   Juan    6 年前

    Tha应用程序与服务器有TLS连接。
    您可以要求服务器将这些CRL URL传递给您(它首先是在传递证书,对吗?)。
    它甚至可以提前完成,并与CRL一起提供证书。 通过这种方式,您可以在不丢失https锁的情况下获得CRL,也不必进行例外。