原创

カールは機能しますが、Kotlin の RestTemplate から実行すると同じリクエストが失敗します

温馨提示:
本文最后更新于 2024年04月12日,已超过 37 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我
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

これは、RestTemplate を使用して Kotlin で実行しようとしているカールコマンドです。シェルからは動作し、適切な出力が得られますが、kotlin コードからは動作させることができません。以下は私のコードです:

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))
    }

このコードにより、次のハンドシェイクエラーが発生します。

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)
       [...]

SSLContext と HttpClient が正しく構成されているとわかりません (オンラインで見つけた例を使用して構成しました)。どこで間違っているかわかりません。助けてください。

注: 秘密キーと証明書は元々 pem ファイルでした。以下の openssl コマンドを使用して、それらを 1 つの p12 ファイルに変換しました。

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