Как правильно создать SSLSocketFactory для двухстороннего TLS? (Для ApplePay) - PullRequest
0 голосов
/ 08 апреля 2020

Я пытаюсь сделать запрос к 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"
}

, что нормально для в той степени, в которой он может взаимодействовать с сервером Apple.

Вот мой код для создания нового клиента 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

Кто-нибудь есть представление о том, что я могу делать неправильно?

1 Ответ

0 голосов
/ 10 апреля 2020

Мой технический руководитель смог помочь решить эту проблему, но ответ @ 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
...