OkHttp转Ktor请求出现Chain validation failed错误求助
问题:OkHttp转Ktor实现后出现
Chain validation failed错误 原OkHttp实现代码
val client = OkHttpClient() val mediaType = MediaType.parse("application/x-www-form-urlencoded") val body = RequestBody.create(mediaType, "tenant_id=xxxx&client_id=xxxx&client_secret=xxxx&resource=xxxx&grant_type=client_credentials") val request = Request.Builder() .url("https://sxxx.com/axxx/oauth2/token") .post(body) .addHeader("Content-Type", "application/x-www-form-urlencoded") .build() val response = client.newCall(request).execute()
我的Ktor实现代码
class Greeting { private val httpClient = HttpClient { } @Throws(Exception::class) suspend fun greeting(): String { val response = httpClient.request { method = HttpMethod.Post url { protocol = URLProtocol.HTTPS host = "sxxx.com" path("axxx/oauth2/token") // encodedParameters trailingQuery = true parameters.append("tenant_id", "xxxx") parameters.append("client_id", "xxxx") parameters.append("client_secret", "xxxx") parameters.append("resource", "xxxx") parameters.append("grant_type", "client_credentials") } headers { append(HttpHeaders.ContentType, "application/x-www-form-urlencoded") } } return response.bodyAsText() } }
调用Ktor代码的方式
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MyApplicationTheme { Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background ) { val scope = rememberCoroutineScope() var text by remember { mutableStateOf("Loading") } LaunchedEffect(true){ scope.launch { text = try { Greeting().greeting() } catch (e: Exception) { e.localizedMessage ?: "error" } } } Greeting(text) } } } } } @Composable fun Greeting(text: String) { Text(text = text) }
遇到的问题
未获取到预期令牌,返回错误:Chain validation failed
解决方案
1. 修正请求格式错误
原OkHttp是将表单参数放在POST请求体中,但你的Ktor代码错误地将参数放到了URL的Query部分,这会导致服务器无法识别参数。正确写法应该把参数放入请求体:
class Greeting { private val httpClient = HttpClient(Android) { // 后续添加SSL配置 } @Throws(Exception::class) suspend fun greeting(): String { val response = httpClient.request { method = HttpMethod.Post url("https://sxxx.com/axxx/oauth2/token") // 指定表单内容类型 contentType(ContentType.Application.FormUrlEncoded) // 将参数放入请求体 setBody(FormDataContent(Parameters.build { append("tenant_id", "xxxx") append("client_id", "xxxx") append("client_secret", "xxxx") append("resource", "xxxx") append("grant_type", "client_credentials") })) } return response.bodyAsText() } }
2. 解决SSL证书验证失败问题
Chain validation failed是SSL证书信任问题,分两种场景处理:
场景一:测试环境(自签名证书)
临时禁用证书验证(生产环境绝对禁止使用):
private val httpClient = HttpClient(Android) { engine { sslManager = SSLManager { trustManager = object : X509TrustManager { override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {} override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {} override fun getAcceptedIssuers(): Array<X509Certificate> = emptyArray() } } } }
场景二:生产环境(正规CA证书)
如果服务器证书是正规CA签发,但系统未信任,可将证书导入项目并配置信任:
- 将证书文件(如
server_cert.pem)放入src/main/res/raw目录 - 配置HttpClient:
private val httpClient = HttpClient(Android) { engine { sslManager = SSLManager { val certInputStream = context.resources.openRawResource(R.raw.server_cert) val certFactory = CertificateFactory.getInstance("X.509") val certificate = certFactory.generateCertificate(certInputStream) as X509Certificate val keyStore = KeyStore.getInstance(KeyStore.getDefaultType()).apply { load(null) setCertificateEntry("server_cert", certificate) } val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()).apply { init(keyStore) } trustManager = trustManagerFactory.trustManagers.first() as X509TrustManager } } }
内容的提问来源于stack exchange,提问作者Hasan A Yousef
相关产品推荐
相关产品推荐

