【问题标题】:java.net.UnknownServiceException: CLEARTEXT communication to t.main.wedeep.com.cn not permitted by network security policyjava.net.UnknownServiceException:网络安全策略不允许与 t.main.wedeep.com.cn 进行 CLEARTEXT 通信
【发布时间】:2020-07-22 10:20:00
【问题描述】:

当我使用mockhttpserver测试http请求时出现上述错误,下面的代码是我如何创建服务的。

   fun <T> getService(clazz: Class<T>): T {
        val client = OkHttpClient.Builder().addInterceptor(HeaderInterceptor()).addInterceptor(HttpLoggingInterceptor().apply { level = if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE })
                .build()
        return Retrofit.Builder()
                .baseUrl(mockWebServer.url(""))
                .client(client)
                .addConverterFactory(GsonConverterFactory.create(GSON))
                .build()
                .create(clazz)
    }

这是我的测试代码。

@UninstallModules(HomePageDataModule::class)
@HiltAndroidTest
class TestHomePageViewModel {


    private lateinit var viewModel: HomePageViewModel

    @get:Rule
    var hiltRule = HiltAndroidRule(this)

    @Inject
    lateinit var cpd: CompositionDao

    @Inject
    lateinit var csd: CompositionsDao

    @Inject
    lateinit var hpds: HomePageDataSource

    @Inject
    lateinit var ss :HomePageService

    @Before
    fun init() {
        hiltRule.inject()
        viewModel = HomePageViewModel(HomeCompositionsRepository(cpd, csd, hpds, Util.GSON))

    }





    @Test
    fun testObserveHomeData() {

        val data = Util.getFileString("mainpage.json")
        val rr  = GSON.fromJson(data,Array<HomePreviewView>::class.java)
        println(rr)
        enqueueResponse("mainpage.json")
        runBlocking {
            val result = ss.getHomeData()
            Assert.assertNotEquals(rr.size,result.body()!!.size)
        }
}

除了运行我的单元测试代码之外,我的应用程序一切正常。 有一个类似的 problem ,但我的问题与那个有一点不同。 我尝试过类似问题的很多方法,但都不起作用。

PS:如果测试代码在 Junit4Test 而不是 AndroidJunit4Test 上运行,它可以正常工作。但现在我需要执行集成测试。所以这部分代码需要在AndroidJunit4Test上执行

【问题讨论】:

  • 确保您的主机对您的应用程序来说是安全的,或者您可以在清单文件中添加这行代码。 android:usesCleartextTraffic="true"
  • @AslamHossin 我不知道为什么当我执行上面的单元测试代码时它对我不起作用。
  • @Cyrus 当该属性设置为“false”时,平台组件(例如,HTTP 和 FTP 堆栈、DownloadManager 和 MediaPlayer)将拒绝应用程序使用明文流量的请求。强烈建议第三方库也遵守此设置。避免明文流量的关键原因是缺乏机密性、真实性和防篡改保护;网络攻击者可以窃听传输的数据并在不被发现的情况下对其进行修改。更多developer.android.com/guide/topics/manifest/…
  • 您也可以使用 mockWebServer.useTls 和 client.insecureHost 来使用 SSL 进行测试连接。

标签: android okhttp android-9.0-pie download-manager


【解决方案1】:

解决方案 1)

将以下属性添加到 AndroidManifest.xml 中的&lt;application 标签:

android:usesCleartextTraffic="true"

解决方案 2)

android:networkSecurityConfig="@xml/network_security_config" 添加到app/src/main/AndroidManifest.xml 中的&lt;application 标记中:

<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:networkSecurityConfig="@xml/network_security_config"
        android:theme="@style/AppTheme">

app/src/main/res/xml/ 中有对应的network_security_config.xml

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

【讨论】:

  • 发布错误,还分享了其他详细信息,如设备、sdk 等
  • 我不知道为什么,但解决方案 2 在 api 30 中对我有用
【解决方案2】:

根据@Yuri Schimke 提示,问题终于解决了。

第一步:mockwebserver使用https

 val mockWebServer = MockWebServer().apply {
        val localhost: String = InetAddress.getByName("localhost").canonicalHostName
        val localhostCertificate: HeldCertificate = HeldCertificate.Builder().addSubjectAlternativeName(localhost)
                .build()
        val serverCertificates = HandshakeCertificates.Builder()
                .heldCertificate(localhostCertificate)
                .build()
        useHttps(serverCertificates.sslSocketFactory(), false)
    }

第二步:使用不安全的okhttp客户端

  private fun getUnsafeOkHttpClient(): OkHttpClient.Builder? {
        return try {
            // Create a trust manager that does not validate certificate chains
            val trustAllCerts: Array<TrustManager> = arrayOf<TrustManager>(
                    object : X509TrustManager {
                        @Throws(CertificateException::class)
                        override fun checkClientTrusted(chain: Array<X509Certificate?>?, authType: String?) {
                        }

                        @Throws(CertificateException::class)
                        override fun checkServerTrusted(chain: Array<X509Certificate?>?, authType: String?) {
                        }

                        override fun getAcceptedIssuers(): Array<X509Certificate> {
                            return arrayOf()
                        }


                    }
            )

            // Install the all-trusting trust manager
            val sslContext: SSLContext = SSLContext.getInstance("SSL")
            sslContext.init(null, trustAllCerts, SecureRandom())

            // Create an ssl socket factory with our all-trusting manager
            val sslSocketFactory: SSLSocketFactory = sslContext.getSocketFactory()
            val builder: OkHttpClient.Builder = OkHttpClient.Builder()
            builder.sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
            builder.hostnameVerifier(HostnameVerifier { hostname, session -> true })
            builder
        } catch (e: Exception) {
            throw RuntimeException(e)
        }
    }

完成此操作后,您可以按照以下代码创建自己的服务。

fun <T> getService(clazz: Class<T>): T {
        val client =getUnsafeOkHttpClient()!!.addInterceptor(HeaderInterceptor())
                .addInterceptor(HttpLoggingInterceptor().apply { level = if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE })
                .build()
        return Retrofit.Builder()
                .baseUrl(mockWebServer.url(""))
                .client(client)
                .addConverterFactory(GsonConverterFactory.create(GSON))
                .build()
                .create(clazz)
    }

如果您在 AndroidJunit4 上有 okhttp 单元测试,希望这会有所帮助

【讨论】:

  • 谢谢,这真的很有帮助!
【解决方案3】:

在我的例子中,我将它添加到了 android 清单文件中:

android:usesCleartextTraffic="true"

【讨论】:

    猜你喜欢
    • 2020-05-01
    • 2020-05-08
    • 2020-05-27
    • 1970-01-01
    • 2020-10-30
    • 2020-11-23
    • 1970-01-01
    • 1970-01-01
    • 2016-06-28
    相关资源
    最近更新 更多