原创

curl 可以工作,但从 Kotlin 中的 RestTemplate 执行时,相同的请求失败

温馨提示:
本文最后更新于 2024年04月12日,已超过 48 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我
curl --request POST --url 'https://myurl' --header 'content-type: application/x-www-form-urlencoded' --data grant_type=client_credentials --data 'client_id=performance-client' --cert mycert.pem --key mykey.pem

This is the curl command I'm trying to execute in Kotlin using RestTemplate. It works from shell and gives the right output but I'm unable to make it work from my kotlin code. Below is my code:

fun generateToken(): QuantumKAccessTokenResponse {
        val headers = HttpHeaders()
        headers.contentType = MediaType.APPLICATION_FORM_URLENCODED
        val requestBody: MultiValueMap<String, String> = LinkedMultiValueMap()
        requestBody.add("grant_type", "client_credentials")
        requestBody.add("client_id", "performance-client")
        val requestEntity = HttpEntity(requestBody, headers)
        val client = getHttpsClient()
        val response = client.postForEntity(quantumKUrl, requestEntity, QuantumKAccessTokenResponse::class.java)
        logger.info("Received a ${response.statusCode.value()} response when fetching access token")
        return response.body ?: QuantumKAccessTokenResponse()
    }

private fun getHttpsClient(): RestTemplate {
        val keyStore = KeyStore.getInstance("PKCS12")
        keyStore.load(ClassPathResource("qk_certificate.p12").inputStream, null)
        val sslContext = SSLContexts.custom()
            .loadKeyMaterial(keyStore, null)
            .build()

        val client = HttpClientBuilder.create()
            .setSSLContext(sslContext)
            .build()

        return RestTemplate(HttpComponentsClientHttpRequestFactory(client))
    }

This code results in the following handshake error:

org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://myurl": Remote host terminated the handshake; nested exception is javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake
       org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:791)
       org.springframework.web.client.RestTemplate.execute(RestTemplate.java:717)
       org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:474)
       com.company.QuantumKAccessTokenGenerator.generateToken(QuantumKAccessTokenGenerator.kt:37)
       com.company.QuantumKAccessTokenGeneratorTest.testGenerateToken(QuantumKAccessTokenGeneratorTest.kt:10)
       [...]
     Caused by: javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake
       java.base/sun.security.ssl.SSLSocketImpl.handleEOF(SSLSocketImpl.java:1701)
       java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1519)
       java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1421)
       java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:456)
       java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:427)
       [...]
       Suppressed: java.net.SocketException: Broken pipe (Write failed)
         java.base/java.net.SocketOutputStream.socketWrite0(Native Method)
         java.base/java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:110)
         java.base/java.net.SocketOutputStream.write(SocketOutputStream.java:150)
         java.base/sun.security.ssl.SSLSocketOutputRecord.encodeAlert(SSLSocketOutputRecord.java:81)
         java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:396)
         [...]
     Caused by: java.io.EOFException: SSL peer shut down incorrectly
       java.base/sun.security.ssl.SSLSocketInputRecord.read(SSLSocketInputRecord.java:489)
       java.base/sun.security.ssl.SSLSocketInputRecord.readHeader(SSLSocketInputRecord.java:478)
       java.base/sun.security.ssl.SSLSocketInputRecord.decode(SSLSocketInputRecord.java:160)
       java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:111)
       java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1511)
       [...]

I'm not sure if I have configured the SSLContext and the HttpClient correctly (I used examples I found online to configure them) and unable to figure out where I went wrong. Please help.

Note: The private key and cert were originally pem files. I converted them into one single p12 file using the below openssl command:

openssl pkcs12 -export -inkey key.pem -in cert.pem -out qk_certificate.p12
正文到此结束
热门推荐
本文目录