如何在 Picasso 上启用 TLS v 1.2 以在 Kotlin 中使用 https 加载图像
Posted
技术标签:
【中文标题】如何在 Picasso 上启用 TLS v 1.2 以在 Kotlin 中使用 https 加载图像【英文标题】:How can i enable TLS v 1.2 on Picasso for loading images with https in Kotlin 【发布时间】:2020-11-08 18:40:32 【问题描述】:根据我对堆栈的研究,我已经在 Kotlin 中实现了一个解决方案
我创建了一个自定义 Kotlin 类,它实现了 SSLSocketFactory 类,还添加了用于将该类传递给加载我的图像的活动的代码。我的代码编译成功,因为没有交配错误,但很难从添加的链接加载我的图像。
这是自定义类 Tls12SocketFactory.kt
import java.io.IOException
import java.net.Socket
import javax.net.ssl.SSLSocket
import javax.net.ssl.SSLSocketFactory`
class Tls12SocketFactory (
private val delegate : SSLSocketFactory //constructor..u need to pass an instance of SSL Socket factory
) : SSLSocketFactory()
private val protocols = arrayOf("TLSv1.1","TLSv1.2") //array of two version of TLS
override fun getDefaultCipherSuites(): Array<String> = delegate.defaultCipherSuites //return an array of strings
//a variable of defaultCipherSuites returns an array of strings
override fun getSupportedCipherSuites(): Array<String> = delegate.supportedCipherSuites //return an array of strings
//four parameterss..it uses it to create socket..no return value..for creating sockets
override fun createSocket(s: Socket, host: String, port: Int, autoClose: Boolean) =
enableTLSOnSocket(delegate.createSocket(s, host, port, autoClose))
//another socket no return typ..assign
override fun createSocket(host: String, port: Int) =
enableTLSOnSocket(delegate.createSocket(host, port))
//no return type..reduces code by eliminating brace = inplace of
override fun createSocket(host: String, port: Int, localHost: InetAddress, localPort: Int) =
enableTLSOnSocket(delegate.createSocket(host, port, localHost, localPort))
//no return type
override fun createSocket(host: InetAddress, port: Int) =
enableTLSOnSocket(delegate.createSocket(host, port))
//no return type
override fun createSocket(address: InetAddress, port: Int, localAddress: InetAddress, localPort: Int) =
enableTLSOnSocket(delegate.createSocket(address, port, localAddress, localPort))
//a nullable parameter and no return type for it not to be null socket!.apply
private fun enableTLSOnSocket(socket: Socket?) = socket?.apply
//if the socket is an instance of SSLSocket
if (this is SSLSocket && isTLSServerEnabled(this))
enabledProtocols = protocols
private fun isTLSServerEnabled(sslSocket: SSLSocket) = sslSocket.supportedProtocols.any it in protocols
我还在我的主要活动类中创建了两个函数
第一个函数是provideX509TrustManager,它返回下面的X509TrustManager
private fun provideX509TrustManager(): X509TrustManager?
try
//its a staic class calling the getInstance method which takes a params of DefaultAlgorithm
val factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
//this is casting null as Keystore
factory.init(null as KeyStore?)
//referencing a variable inside TrustManagerFactory
val trustManagers = factory.trustManagers
//returns the first element in trustManager and cast as X509TrustManager
return trustManagers[0] as X509TrustManager
catch (exception: NoSuchAlgorithmException)
Log.e(javaClass.simpleName, "not trust manager available", exception)
catch (exception: KeyStoreException)
Log.e(javaClass.simpleName, "not trust manager available", exception)
return null
另一个函数是finalConvert,它返回一个OkHttpClient对象,也传递了我上面声明的方法
//returns OKHttpClient
fun finalConvert() : OkHttpClient
//gets an sslcontext
val sslContext: SSLContext = SSLContext.getInstance("TLSv1.2")
sslContext.init(null, null, null)
val noSSLv3Factory: SSLSocketFactory
noSSLv3Factory = if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT)
Tls12SocketFactory(sslContext.socketFactory)
else
sslContext.socketFactory
//OkHttpClient is built
val okb = OkHttpClient.Builder()
.sslSocketFactory(noSSLv3Factory, provideX509TrustManager()!!)
return okb.build();
最后,在我的 onCreate 中,我将方法传递给了在 Picasso 对象上调用的下载器方法,如下所示
try
val p = Picasso.Builder(this)
.downloader(OkHttp3Downloader(finalConvert()))
.build()
p.load(
"https://sdo.gsfc.nasa.gov/assets/img/latest/latest_2048_HMIIC.jpg")
.fit().centerCrop()
.placeholder(android.R.drawable.sym_contact_card)
.error(android.R.drawable.sym_def_app_icon)
.into(img_pics)
catch (e: Exception)
Toast.makeText(this," error as a result of " + e.localizedMessage,Toast.LENGTH_LONG).show()
这是我的 build.graddle 文件。我不知道我做错了什么
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android
compileSdkVersion 29
buildToolsVersion "30.0.0"
defaultConfig
applicationId "com.gitapp.tlsimageloader"
minSdkVersion 16
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
buildTypes
release
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
dependencies
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
//implementation 'com.squareup.picasso:picasso:2.71828'
//implementation 'com.squareup.picasso:picasso:2.4.0'
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
implementation 'com.squareup.picasso:picasso:2.5.2'
implementation 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.0.2'
implementation 'androidx.core:core-ktx:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
//implementation 'com.squareup.okhttp3:okhttp:4.7.2'
implementation 'com.github.bumptech.glide:glide:4.11.0'
// Glide v4 uses this new annotation processor -- see https://bumptech.github.io/glide/doc/generatedapi.html
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7'
testImplementation 'com.squareup.okhttp3:mockwebserver:4.7.2'
完整代码here
【问题讨论】:
【参考方案1】:OkHttp 会自动为您执行此操作。只需升级到 3.12.12 或 4.8.0 并删除大部分代码。
https://github.com/square/okhttp/blob/okhttp_3.12.x/okhttp/src/main/java/okhttp3/internal/platform/AndroidPlatform.java#L442-L465
【讨论】:
我做了升级...从答案似乎没有变化,因为图像还没有加载..你能提供更多上下文 Yuri 请你指出我需要删除的代码 Tls12SocketFactory,提供X509TrustManager。只需调用 OkHttpClient()以上是关于如何在 Picasso 上启用 TLS v 1.2 以在 Kotlin 中使用 https 加载图像的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Android 应用程序中启用 TLS 1.2 支持(在 Android 4.1 JB 上运行)
如何在Android应用程序中启用TLS 1.2支持(在Android 4.1 JB上运行)