RSc*_*son 7 ssl android tls1.2 retrofit2 okhttp3
我正在开发一个应用程序,我必须通过HTTPS与具有自签名证书的嵌入式IoT产品进行通信.我成功设置了OkHttp以使用自签名证书,并通过RxCallAdapters通过Retrofit2进行网络调用.
嵌入式产品一次只能处理一个连接,所以我将我的底层OkHttp实例配置为只允许一个连接(据我所知,也许有更好的方法).
如果我只是发出GET请求,则握手成功完成,并且连接对整个请求序列保持打开状态.嵌入式产品在5秒钟不活动后关闭连接,因此我需要每隔一段时间重新进行一次握手.
在执行PUT和POST请求时会出现问题.当请求流从一种请求类型更改为另一种请求类型时,OkHttp似乎不会保持现有连接打开,或者实际上只要请求是PUT或POST.例如:
握手 - 得 - 握 - 握 - 握手 - 握 - 握手 - 得......等等
如何强制OkHttp在不同类型的请求之间保持连接打开?我知道它应该没关系,但似乎与响应代码有关.嵌入式设备上的REST API为GET提供200,为POST提供201,为PUT提供204.
这是我用来配置OkHttp和我的改造实例的相关代码:
@Provides
@Singleton
fun provideHttpLoggingInterceptor(): HttpLoggingInterceptor {
val httpLoggingInterceptor = HttpLoggingInterceptor { message -> Timber.tag("OkHttp").d(message) }
setLogLevel(httpLoggingInterceptor)
return httpLoggingInterceptor
}
private fun setLogLevel(httpLoggingInterceptor: HttpLoggingInterceptor) {
if (BuildConfig.DEBUG) {
httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
} else {
httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.NONE
}
}
@Provides
@Singleton
fun provideContentTypeHeaderInterceptor(): Interceptor {
return Interceptor { chain ->
val originalRequest = chain.request()
val requestBuilder = originalRequest.newBuilder()
requestBuilder.header("Content-Type", "application/json")
chain.proceed(requestBuilder.build())
}
}
@Provides
@Singleton
@LocalOkHttpConnectionPool
fun provideLocalConnectionPool() = ConnectionPool(1, 5, TimeUnit.SECONDS)
@Provides
@Singleton
@LocalOkHttpClient
fun provideLocalOkHttpClient(headerInterceptor: Interceptor,
httpLoggingInterceptor: HttpLoggingInterceptor,
@LocalOkHttpConnectionPool connectionPool: ConnectionPool,
context: Context): OkHttpClient {
val cf = CertificateFactory.getInstance("X.509")
val cert = context.getResources().openRawResource(R.raw.ca) // Place your 'my_cert.crt' file in `res/raw`
val ca = cf.generateCertificate(cert)
cert.close()
val keyStoreType = KeyStore.getDefaultType()
val keyStore = KeyStore.getInstance(keyStoreType)
keyStore.load(null, null)
keyStore.setCertificateEntry("ca", ca)
val tmfs = CompositeX509TrustManager.getTrustManagers(keyStore)
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, tmfs, null)
val hostNameVerifier = HostnameVerifier { hostname, session ->
return@HostnameVerifier true
}
val connectionSpec = ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.allEnabledCipherSuites()
.allEnabledTlsVersions()
.supportsTlsExtensions(true)
.build()
val connectionSpecs = mutableListOf(connectionSpec)
val okHttpClient = OkHttpClient.Builder()
.connectionSpecs(connectionSpecs)
.hostnameVerifier(hostNameVerifier)
.addInterceptor(headerInterceptor)
.addInterceptor(httpLoggingInterceptor)
.connectionPool(connectionPool)
.sslSocketFactory(sslContext.socketFactory, tmfs.first() as X509TrustManager)
.connectTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.build()
return okHttpClient
}
@Provides
@Singleton
@LocalRetrofit
fun provideLocalRetrofit(@LocalOkHttpClient okHttpClient: OkHttpClient,
gson: Gson): Retrofit {
return Retrofit.Builder().baseUrl(NetworkUtils.BASE_AUTH_URL)
.addConverterFactory(NullOnEmptyConverterFactory())
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient)
.build()
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
310 次 |
| 最近记录: |