首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Ktor客户端Auth功能不发送授权头

Ktor客户端Auth功能不发送授权头
EN

Stack Overflow用户
提问于 2020-04-22 10:11:37
回答 2查看 5.1K关注 0票数 7

我试图在Kotlin/MPP (多平台)项目中使用ktor 客户端,而在JVM目标特性上基本认证似乎没有效果。

下面是一个重现的例子:

代码语言:javascript
运行
复制
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头,但是当手动提供此类头时,我没有遇到任何问题:

第一个请求(失败的示例:)

代码语言:javascript
运行
复制
[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

第二个请求(后续示例:)

代码语言:javascript
运行
复制
[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

环境

  • Kotlin: 1.4-M1

Ktor工件版本1.3.1:

  • ktor-客户核心
  • ktor-客户机日志
  • 客户-json
  • ktor-客户端序列化
  • ktor-客户-基本

我错过了什么吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-04-25 23:46:30

请添加sendWithoutRequest = true

1.x https://api.ktor.io/1.3.1/io.ktor.client.features.auth.providers/-basic-auth-config/send-without-request.html

代码语言:javascript
运行
复制
install(Auth) {
    basic {
        sendWithoutRequest = true
        username = "user"
        password = "pass"
    }
}

2.x https://ktor.io/docs/basic-client.html#configure

代码语言:javascript
运行
复制
install(Auth) {
    basic {
        sendWithoutRequest { true }
        credentials {
            BasicAuthCredentials(
                username = "user",
                password = "pass",
            )
        }
    }
}

结果:

代码语言:javascript
运行
复制
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之后。

代码语言:javascript
运行
复制
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

票数 12
EN

Stack Overflow用户

发布于 2022-08-23 15:34:47

Ktor 2.1.0

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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")
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61362485

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档