问题描述
我关注 this tutorial 使用 Volley 进行安全的 API 调用。
我的活动
class MainActivity : AppCompatActivity() {
private val SECURE_URL = "https://epas.vercel.app/api/v1/login"
private var requestQueue: RequestQueue? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sendRequest()
}
private fun sendRequest() {
requestQueue = Volley.newRequestQueue(this,HurlStack(null,pinnedSSLSocketFactory()))
val request = StringRequest(Request.Method.POST,SECURE_URL,{ response ->
println("_print::Response: $response")
}) { error ->
println("_print::Request Failed: $error")
}
requestQueue!!.add(request)
}
private fun pinnedSSLSocketFactory(): SSLSocketFactory? {
try {
return TLSSocketFactory("SX23A4")
} catch (e: KeyManagementException) {
e.printstacktrace()
} catch (e: NoSuchAlgorithmException) {
e.printstacktrace()
}
return null
}
}
公钥管理器
class PubKeyManager(private val publicKey: String) : x509trustmanager {
@Throws(CertificateException::class)
override fun checkClientTrusted(chain: Array<X509Certificate>,authType: String) {}
@Throws(CertificateException::class)
override fun checkServerTrusted(chain: Array<X509Certificate>,authType: String) {
require(chain.isNotEmpty()) { "checkServerTrusted: X509Certificate is empty" }
// Perform customary SSL/TLS checks
val tmf: TrustManagerFactory
try {
tmf = TrustManagerFactory.getInstance("X509")
tmf.init(null as KeyStore?)
for (trustManager in tmf.trustManagers) {
(trustManager as x509trustmanager).checkServerTrusted(chain,authType)
}
} catch (e: Exception) {
throw CertificateException(e.toString())
}
// Hack ahead: BigInteger and toString(). We kNow a DER encoded Public
// Key starts with 0x30 (ASN.1 SEQUENCE and CONSTRUCTED),so there is
// no leading 0x00 to drop.
val pubkey = chain[0].publicKey as RSAPublicKey
val encoded = BigInteger(1 /* positive */,pubkey.encoded).toString(16)
// Pin it!
val expected = publicKey.equals(encoded,ignoreCase = true)
// fail if expected public key is different from our public key
if (!expected) throw CertificateException("Not trusted")
}
override fun getAcceptedissuers(): Array<X509Certificate?> = arrayOfNulls(0)
}
和 TLSSocketFactory
class TLSSocketFactory(publicKey: String?) : SSLSocketFactory() {
private val internalSSLSocketFactory: SSLSocketFactory
override fun getDefaultCipherSuites(): Array<String> =
internalSSLSocketFactory.defaultCipherSuites
override fun getSupportedCipherSuites(): Array<String> =
internalSSLSocketFactory.supportedCipherSuites
@Throws(IOException::class)
override fun createSocket(s: Socket,host: String,port: Int,autoClose: Boolean): Socket {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s,host,port,autoClose))
}
@Throws(IOException::class)
override fun createSocket(host: String,port: Int): Socket =
enableTLSOnSocket(internalSSLSocketFactory.createSocket(host,port))
@Throws(IOException::class)
override fun createSocket(host: String,localHost: InetAddress,localPort: Int): Socket =
enableTLSOnSocket(internalSSLSocketFactory.createSocket(host,localHost,localPort))
@Throws(IOException::class)
override fun createSocket(host: InetAddress,port))
@Throws(IOException::class)
override fun createSocket(address: InetAddress,localAddress: InetAddress,localPort: Int): Socket =
enableTLSOnSocket(internalSSLSocketFactory.createSocket(address,localAddress,localPort))
private fun enableTLSOnSocket(socket: Socket): Socket {
if (socket is SSLSocket) {
socket.enabledProtocols = addTLS1And2(socket.enabledProtocols)
}
return socket
}
private fun addTLS1And2(currentProtocols: Array<String>): Array<String> {
var hasTLSv1_1 = false
var hasTLSv1_2 = false
val tlsv11 = "TLSv1.1"
val tlsv12 = "TLSv1.2"
val list = ArrayList(listof(*currentProtocols))
for (protocol in currentProtocols) {
if (protocol == tlsv11) hasTLSv1_1 = true
if (protocol == tlsv12) hasTLSv1_2 = true
}
if (!hasTLSv1_1) list.add(tlsv11)
if (!hasTLSv1_2) list.add(tlsv12)
return list.toTypedArray()
}
init {
val context = SSLContext.getInstance("TLS")
val tm = arrayOf<TrustManager>(PubKeyManager(publicKey!!))
context.init(null,tm,null)
internalSSLSocketFactory = context.socketFactory
}
}
当我在装有 Android 4.2.2 (API 17) 的设备上运行该应用程序时,出现此错误:
Request Failed: com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x516e3e70: Failure in SSL library,usually a protocol error
我也尝试过改造,但遇到了同样的错误。
是否有任何变通方法或推荐的 API 调用方式来使用 volley 或改造旧设备上的 MODEL_TLS 服务器?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)