Android 8:不允许明文HTTP流量

1686

我收到来自使用Android 8的用户的报告,称我的应用程序(使用后端提要)无法显示内容。经过调查,我发现在Android 8上发生以下异常:

08-29 12:03:11.246 11285-11285/ E/: [12:03:11.245, main]: Exception: IOException java.io.IOException: Cleartext HTTP traffic to * not permitted
at com.android.okhttp.HttpHandler$CleartextURLFilter.checkURLPermitted(HttpHandler.java:115)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:458)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:127)
at com.deiw.android.generic.tasks.AbstractHttpAsyncTask.doConnection(AbstractHttpAsyncTask.java:207)
at com.deiw.android.generic.tasks.AbstractHttpAsyncTask.extendedDoInBackground(AbstractHttpAsyncTask.java:102)
at com.deiw.android.generic.tasks.AbstractAsyncTask.doInBackground(AbstractAsyncTask.java:88)
at android.os.AsyncTask$2.call(AsyncTask.java:333)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)

在 Android 7 及以下版本上,一切正常。我没有在 Manifest 中设置 android:usesCleartextTraffic(将其设置为 true 也没有帮助,因为默认值就是这个),也没有使用网络安全信息。如果我调用 NetworkSecurityPolicy.getInstance().isCleartextTrafficPermitted(),它会返回 false(针对 Android 8),返回 true(针对旧版本),并且仍然使用同一个 apk 文件。 我试图在 Google 上寻找 Android O 相关的信息,但未获得成功。


6
由于服务器在某些情况下将HTTPS重定向到HTTP,导致我维护的应用程序出现了这种情况。 - Big McLargeHuge
请在此处查看:https://codechacha.com/android-cleartext-http-traffic-issue/ - ikmazameti
我正在构建API级别为30的Android 11应用程序,并在清单文件中的应用程序标记中添加android:usesCleartextTraffic="true"。 - masterxilo
据其他地方报道,直到Android 9才会发生这种情况。这对我来说是个新闻。 - undefined
37个回答

4

创建文件 - res / xml / network_security.xml

在network_security.xml中 ->

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">192.168.0.101</domain>
    </domain-config>
</network-security-config>

打开 AndroidManifests.xml 文件:
 android:usesCleartextTraffic="true" //Add this line in your manifests

<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:usesCleartextTraffic="true"
        android:theme="@style/AppTheme">

3

只需在AndroidManifest.xml文件中的<application>标签中添加android:usesCleartextTraffic="true"即可。


2

对于Xamarin.Android开发者,请确保HttpClient实现和SSL/TLS设置为默认值。

可以在Andorid选项 -> 高级Android选项下找到。

enter image description here


2

出于安全原因,您应该尽可能使用 HTTPS(HTTP 安全)。
您可以在这里阅读更多相关信息。

针对此问题,取决于您的情况,有多种解决方案。

如果您正在尝试与第一方服务通信,例如您自己的 Web 服务器

服务器端:您应该为该服务器添加 HTTPS 支持并使用 HTTPS 而不是 HTTP。如今,您甚至可以使用像 LetsEncrypt其他服务 这样的免费服务来执行此操作。
客户端:如果您正在使用 java.net 包中的 HttpURLConnection,则可以切换到 java.net.ssl 包中的 HttpsURLConnection,它具有类似或相同的 API,因此切换应该很轻松。

如果您正在使用第三方服务,例如 Google、Facebook、天气服务等

如果您正在通信的服务支持HTTPS(大多数情况下都是),您只需将请求URL从http://abc.xyz更改为https://abc.xyz即可。
作为最后的选择,如果您想要通信的第三方服务不支持HTTPS或任何其他形式的安全通信,您可以使用this answer,但这并不推荐,因为它会破坏这个非常必要的安全功能的目的。

这个问题的关键是绝大多数服务器不支持运行https。它会在负载均衡器前面的服务器上卸载。为了使用TLS,我需要安装nginx并将SSL卸载到本地主机的8080端口或其他端口上。因为嘿,我这里不是在测试Android,而是在测试后端。所以我不能构建apk文件。 - undefined

2

videoView不能打开这个在线视频

创建文件res/xml/network_security_config.xml

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <certificates src="system" />
        </trust-anchors>
    </base-config>
</network-security-config>

在AndroidManifest.xml文件中,application标签下新增内容:
android:networkSecurityConfig="@xml/network_security_config"

https://techprogrammingideas.blogspot.com/2021/02/android-code-for-displaying-video-with.html

https://youtu.be/90hWWAqfdUU

是的,这对我来说可行,适用于Android 10/11/12。 - BollMose

2

如果你正在使用 ionic 并在使用本地http插件时遇到此错误,需要执行以下修复操作-

前往 resources/android/xml/network_security_config.xml 将其更改为-

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">localhost</domain>
        <domain includeSubdomains="true">api.example.com(to be adjusted)</domain>
    </domain-config>
</network-security-config>

这对我很有用!


2

我正在使用Cordova 8和cordova-plugin-whitelist 1.3.4,根据默认配置,我的应用程序无法访问互联网,我只需在manifest.xml中添加一个参数即可-> android:usesCleartextTraffic="true"

在Cordova 8中,主文件路径已更改:platform/android/app/src/main/AndroidManifest.xml。

 <?xml version='1.0' encoding='utf-8'?>
    <manifest android:hardwareAccelerated="true" android:versionCode="10000" android:versionName="1.0.0" package="io.cordova.hellocordova" xmlns:android="http://schemas.android.com/apk/res/android">
        <supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:resizeable="true" android:smallScreens="true" android:xlargeScreens="true" />
        <application 
android:hardwareAccelerated="true" 
android:icon="@mipmap/ic_launcher" 
android:label="@string/app_name" 
android:supportsRtl="true" 
android:usesCleartextTraffic="true">
            <activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode" android:label="@string/activity_name" android:launchMode="singleTop" android:name="MainActivity" android:theme="@android:style/Theme.DeviceDefault.NoActionBar" android:windowSoftInputMode="adjustResize">
                <intent-filter android:label="@string/launcher_name">
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    </manifest>

这是一个非常愚蠢的问题,因为很明显你的应用程序需要访问互联网...


2
在我的情况下,该URL在浏览器中也无法正常工作。
我已经检查过 https://www.google.com/
webView.loadUrl("https://www.google.com/")

"它对我起作用了。"

myWebView.loadUrl("www.site.com"); 也适用于没有SSL(HTTPS)但只有HTTP的网站管理员。可能会得到空白页面。 - Bay
如果在您的网页浏览器中可以打开给定的URL,则可以在您的Web视图中使用。否则,您将看到此错误。 - Mayuresh Deshmukh
我知道有时会出现错误,但大多数情况下,即使运行javascript是“true”,我也看到空白页面,并且可以正确访问网站。我不知道为什么会看到空白页面,而且我设置了可缩放为真。 - Bay

1

明文是指未加密或不打算加密的任何传输或存储信息。

当应用程序使用明文网络流量(例如HTTP,而非HTTPS)与服务器通信时,可能会增加被黑客攻击和篡改内容的风险。第三方可以注入未经授权的数据或泄露有关用户的信息。因此,开发人员被鼓励仅保护流量,例如使用HTTPS。这里是如何解决此问题的实现和参考。


1
我们面临了一个非常相似的问题,找出解决方法十分困难。对于那些不幸需要处理此类问题的人,以下是我们所做的:
ionic应用在浏览器(Chrome和Firefox)中运行正常,在苹果应用商店上部署后,与我们在AWS上的API通信也正常。然后我们开始进行Android构建。在模拟器中,我们的https API请求甚至都没有被发送出去。在物理设备上,“内部测试”后https请求也无法发送出去。
在模拟器中运行应用程序 打开Chrome,键入“chrome://inspect”,等待,单击到模拟器实例的链接,然后可以查看网络选项卡。请求会快速循环从(挂起)到(取消),而不会被发送到服务器。
在Stackoverflow上搜索了很久,主要建议是使用cleartextPermitted工作方式禁用https,这是一个可怕的想法。
另一个常见的建议是使用本机http,但如果我们必须有两个代码库,那么使用ionic还有什么意义呢?我想保留我的http拦截器。
添加了一个network_security_config.xml文件(这可能并不是严格必要的,但它可以消除Android Studio中的编译警告)。

通过在浏览器中点击锁图标,检查我们服务器上的SSL证书。看起来没问题。(也许是因为它真的有问题,但我曾经添加了一个手动覆盖,而我已经忘记了)。 还有很多其他的问题。

最后使用sslshopper的工具验证我们的SSL证书: https://www.sslshopper.com/ssl-checker.html

结果发现虽然我们的证书没问题,但证书链出了问题。这会在他们的诊断中显示为一个红色的断开箭头。

基本上,你需要将你的SSL证书和组织提供证书的SSL证书连接起来,以及任何证明认证者的其他SSL证书,直到整个链路干净为止。我们使用了提供的捆绑包,但它没有足够地向上穿过链路

修复SSL链:

cat your-purchased-cert-site-com.crt > your-site.bundle.crt
cat other-org-cert-sectigoRSA-bla-bla-bla.crt >> your-site.bundle.crt
cat another-org-cert-USERTrust-bla-bla-bla.crt >> your-site.bundle.crt
cat some-final-high-level-org-cert.crt >> your-site.bundle.crt

然后,在我们的情况下,对于Ubuntu上的nginx:

将your-site.bundle.crt放在可用的位置。(在我们的情况下,是/var/ssl)

update /etc/nginx/sites-available/site-name.conf:
ssl_certificate /var/ssl/your-site.bundle.crt
ssl_certificate /var/ssl/your-private-key.key

重新启动您的Web服务器(在我们的情况下为nginx:sudo systemctl restart nginx)

使用sslshopper的检查器进行检查,您应该看到一路绿箭头。

启动了我们的模拟器,API调用直接通过。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接