我试图在Kotlin/MPP (多平台)项目中使用ktor 客户端,而在JVM目标特性上基本认证似乎没有效果。
下面是一个重现的例子:
import io.ktor.client.HttpClient
import io.ktor.client.features.ResponseException
import io.ktor.client.features.auth.Auth
import io.ktor.client.features.auth.providers.basic
import io.ktor.client.features.json.JsonFeature
import io.ktor.client.features.json.serializer.KotlinxSerializer
import io.ktor.client.features.logging.DEFAULT
import io.ktor.client.features.logging.LogLevel
import io.ktor.client.features.logging.Logger
import io.ktor.client.features.logging.Logging
import io.ktor.client.request.get
import io.ktor.client.request.header
import kotlinx.coroutines.runBlocking
import java.util.*
fun main() = runBlocking {
val client = HttpClient {
install(Logging) {
logger = Logger.DEFAULT
level = LogLevel.HEADERS
}
install(JsonFeature) {
serializer = KotlinxSerializer()
}
install(Auth) {
basic {
username = "user"
password = "pass"
}
}
}
val url = "https://en.wikipedia.org/wiki/Main_Page"
val failing = try {
client.get<String>(url)
} catch (e: ResponseException) {
"failed"
}
val succeeding = try {
client.get<String>(url) {
header("Authorization", "Basic ${Base64.getEncoder().encodeToString("user:pass".toByteArray())}")
}
} catch (e: ResponseException) {
"failed"
}
}
观察
从记录器输出中,您可以看到客户端不发送Authorization
头,但是当手动提供此类头时,我没有遇到任何问题:
第一个请求(失败的示例:)
[main] INFO io.ktor.client.HttpClient - REQUEST: https://en.wikipedia.org/wiki/Main_Page
[main] INFO io.ktor.client.HttpClient - METHOD: HttpMethod(value=GET)
[main] INFO io.ktor.client.HttpClient - COMMON HEADERS
[main] INFO io.ktor.client.HttpClient - -> Accept: application/json
[main] INFO io.ktor.client.HttpClient - -> Accept-Charset: UTF-8
[main] INFO io.ktor.client.HttpClient - CONTENT HEADERS
第二个请求(后续示例:)
[main] INFO io.ktor.client.HttpClient - REQUEST: https://en.wikipedia.org/wiki/Main_Page
[main] INFO io.ktor.client.HttpClient - METHOD: HttpMethod(value=GET)
[main] INFO io.ktor.client.HttpClient - COMMON HEADERS
[main] INFO io.ktor.client.HttpClient - -> Authorization: Basic dXNlcjpwYXNz
[main] INFO io.ktor.client.HttpClient - -> Accept: application/json
[main] INFO io.ktor.client.HttpClient - -> Accept-Charset: UTF-8
[main] INFO io.ktor.client.HttpClient - CONTENT HEADERS
环境
Ktor工件版本1.3.1:
我错过了什么吗?
发布于 2020-04-25 23:46:30
请添加sendWithoutRequest = true
install(Auth) {
basic {
sendWithoutRequest = true
username = "user"
password = "pass"
}
}
2.x https://ktor.io/docs/basic-client.html#configure
install(Auth) {
basic {
sendWithoutRequest { true }
credentials {
BasicAuthCredentials(
username = "user",
password = "pass",
)
}
}
}
结果:
sending with sendWithoutRequest set to true
[main] INFO io.ktor.client.HttpClient - REQUEST: https://en.wikipedia.org/wiki/Main_Page
[main] INFO io.ktor.client.HttpClient - METHOD: HttpMethod(value=GET)
[main] INFO io.ktor.client.HttpClient - COMMON HEADERS
[main] INFO io.ktor.client.HttpClient - -> Authorization: Basic dXNlcjpwYXNz
[main] INFO io.ktor.client.HttpClient - -> Accept: application/json
[main] INFO io.ktor.client.HttpClient - -> Accept-Charset: UTF-8
[main] INFO io.ktor.client.HttpClient - CONTENT HEADERS
解释:
默认情况下,Ktor将等待服务器响应401,未经授权,然后才发送身份验证头。在您的示例中,wiki从不使用401响应,因为它不是受保护的资源。因此,需要添加sendWithoutRequest。如果您尝试使用某些url来响应401,那么您将看到Ktor将使用身份验证头发送第二个请求(在接收401之后)。您可以尝试使用这个url来查看- https://api.sumologic.com/api/v1/collectors。
这是在关闭sendWithoutRequest (原始输入)的情况下对受保护的api执行日志记录。如您所见,现在有两个请求,第一个没有授权头,第二个没有授权头,在服务器响应401之后。
sending with sendWithoutRequest set to false and hitting a protected resource
[main] INFO io.ktor.client.HttpClient - REQUEST: https://api.sumologic.com/api/v1/collectors
[main] INFO io.ktor.client.HttpClient - METHOD: HttpMethod(value=GET)
[main] INFO io.ktor.client.HttpClient - COMMON HEADERS
[main] INFO io.ktor.client.HttpClient - -> Accept: application/json
[main] INFO io.ktor.client.HttpClient - -> Accept-Charset: UTF-8
[main] INFO io.ktor.client.HttpClient - CONTENT HEADERS
[main] INFO io.ktor.client.HttpClient - REQUEST: https://api.sumologic.com/api/v1/collectors
[main] INFO io.ktor.client.HttpClient - METHOD: HttpMethod(value=GET)
[main] INFO io.ktor.client.HttpClient - COMMON HEADERS
[main] INFO io.ktor.client.HttpClient - -> Accept: application/json
[main] INFO io.ktor.client.HttpClient - -> Accept-Charset: UTF-8
[main] INFO io.ktor.client.HttpClient - -> Authorization: Basic dXNlcjpwYXNz
[main] INFO io.ktor.client.HttpClient - CONTENT HEADERS
注意:我刚刚看到Andylamax的一个评论,一个新版本“修复”了它。也许,我不知道,因为我已经尝试了那个新版本。但我想补充一点,这并不是Ktor独有的事情,至少在这方面不是一个错误(但也许他们改变了主意?)同样,我也不知道)。事实上,正是我在C#上的经验让我怀疑这里发生了什么,并找到了答案。WebRequest在C#中的行为方式与此相同,您需要将PreAuthenticate设置为true才能立即发送凭据。看这里,https://learn.microsoft.com/en-us/dotnet/api/system.net.webrequest.preauthenticate?view=netcore-3.1。
发布于 2022-08-23 15:34:47
Ktor 2.1.0
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.engine.cio.*
import io.ktor.client.plugins.auth.*
import io.ktor.client.plugins.auth.providers.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
private val httpClient = HttpClient(CIO) {
install(Auth) {
basic {
credentials {
BasicAuthCredentials(
username = "user",
password = "pass"
)
}
}
}
}
build.gradle
implementation("io.ktor:ktor-client-core:2.1.0")
implementation("io.ktor:ktor-client-cio:2.1.0")
implementation("io.ktor:ktor-client-auth:2.1.0")
https://stackoverflow.com/questions/61362485
复制相似问题