如何为 2 路 TLS 正确创建 SSLSocketFactory? (适用于苹果支付)
How to properly create an SSLSocketFactory for 2 way TLS? (For ApplePay)
我正在尝试向 ApplePay 发出请求,但无法使用 Java。
这是 curl 请求:
$ curl -X POST --cert-type P12 --cert cert.p12 https://apple-pay-gateway-pr-pod1.apple.com/paymentservices/startSession -d '{}'
{
"statusMessage": "Payment Services Exception Invalid session request",
"statusCode": "400"
}
正常,能和苹果服务器通信。
这是我生成新的 Feign 客户端 SSLContextFactory 的代码(用 Kotlin 编写):
@Bean
fun client(): Client { // a Feign Client
val keystoreFile = File("/path/to/cert.p12")
val keyStore = KeyStore.getInstance("PKCS12")
keyStore.load(keystoreFile.inputStream(), null)
val keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyFactory.init(keyStore, null)
val trustManagerFactory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm()
)
trustManagerFactory.init(keyStore)
val trustManagers = trustManagerFactory.trustManagers
val trustManager = trustManagers[0] as X509TrustManager
val sslContext: SSLContext = SSLContext.getInstance("TLS")
sslContext.init(keyFactory.keyManagers, trustManagers, null)
return feign.okhttp.OkHttpClient(
FeignConfiguration.enrichOkHttpClientBuilder(logbook)
.sslSocketFactory(sslContext.socketFactory, trustManager)
.connectionSpecs(
arrayListOf(
ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_2)
.cipherSuites(
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
, CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
, CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256
, CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256
)
.build()
)
)
.build()
)
}
但是当我尝试向同一个 URL 发出请求时,出现以下错误:
feign.RetryableException: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty executing POST https://apple-pay-gateway-pr-pod1.apple.com/paymentservices/startSession/paymentSession
有人知道我可能做错了什么吗?
我的技术主管能够帮助解决这个问题,但@dave_thompson_085 的回答也应该有所帮助。
所以我基本上将假装客户端之前的部分替换为:
val keystoreStream = <stream>
val keyStore = KeyStore.getInstance("PKCS12")
keyStore.load(keystoreStream, keystorePassword.toCharArray())
val sslContext: SSLContext = SSLContexts.custom()
.loadTrustMaterial(null, TrustSelfSignedStrategy())
.loadKeyMaterial(keyStore, keystorePassword.toCharArray())
.build()
val tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm())
tmf.init(keyStore) // can use tmf to get individual trustmanager
我正在尝试向 ApplePay 发出请求,但无法使用 Java。
这是 curl 请求:
$ curl -X POST --cert-type P12 --cert cert.p12 https://apple-pay-gateway-pr-pod1.apple.com/paymentservices/startSession -d '{}'
{
"statusMessage": "Payment Services Exception Invalid session request",
"statusCode": "400"
}
正常,能和苹果服务器通信。
这是我生成新的 Feign 客户端 SSLContextFactory 的代码(用 Kotlin 编写):
@Bean
fun client(): Client { // a Feign Client
val keystoreFile = File("/path/to/cert.p12")
val keyStore = KeyStore.getInstance("PKCS12")
keyStore.load(keystoreFile.inputStream(), null)
val keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyFactory.init(keyStore, null)
val trustManagerFactory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm()
)
trustManagerFactory.init(keyStore)
val trustManagers = trustManagerFactory.trustManagers
val trustManager = trustManagers[0] as X509TrustManager
val sslContext: SSLContext = SSLContext.getInstance("TLS")
sslContext.init(keyFactory.keyManagers, trustManagers, null)
return feign.okhttp.OkHttpClient(
FeignConfiguration.enrichOkHttpClientBuilder(logbook)
.sslSocketFactory(sslContext.socketFactory, trustManager)
.connectionSpecs(
arrayListOf(
ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_2)
.cipherSuites(
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
, CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
, CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256
, CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256
)
.build()
)
)
.build()
)
}
但是当我尝试向同一个 URL 发出请求时,出现以下错误:
feign.RetryableException: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty executing POST https://apple-pay-gateway-pr-pod1.apple.com/paymentservices/startSession/paymentSession
有人知道我可能做错了什么吗?
我的技术主管能够帮助解决这个问题,但@dave_thompson_085 的回答也应该有所帮助。
所以我基本上将假装客户端之前的部分替换为:
val keystoreStream = <stream>
val keyStore = KeyStore.getInstance("PKCS12")
keyStore.load(keystoreStream, keystorePassword.toCharArray())
val sslContext: SSLContext = SSLContexts.custom()
.loadTrustMaterial(null, TrustSelfSignedStrategy())
.loadKeyMaterial(keyStore, keystorePassword.toCharArray())
.build()
val tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm())
tmf.init(keyStore) // can use tmf to get individual trustmanager