ktor 摘要认证

ktor digest Authentication

我想使用此方法来验证我的应用程序中的 client/server 通信,但无法弄清楚为什么会出错。 代码超级简单,来自原始ktor示例。

服务器:

val myRealm = "Access to the '/' path"
val userTable: Map<String, ByteArray> = mapOf(
    "jetbrains" to getMd5Digest("jetbrains:$myRealm:foobar"),
    "admin" to getMd5Digest("admin:$myRealm:password")


fun Application.configureSecurity() {

    install(Authentication) {

        digest("myDigestAuth") {
            digestProvider { userName, realm ->
                userTable[userName]
            }
        }
    }

    routing {
        authenticate("myDigestAuth") {
            get("/protected/route/digest") {
                val principal = call.principal<UserIdPrincipal>()!!
                call.respondText("Hello ${principal.name}")
            }
        }
    }
}

客户:

val client = HttpClient(CIO) {
    install(Logging) {
        logger = Logger.DEFAULT
        level = LogLevel.HEADERS
    }
    install(Auth) {
        digest {
            credentials {
                DigestAuthCredentials(username = "jetbrains", password = "foobar")
            }
            realm = myRealm
        }
    }
}
val response: HttpResponse =   client.get("http://0.0.0.0:8080/protected/route/digest")

这里是通讯日志:

[DefaultDispatcher-worker-1] INFO  io.ktor.client.HttpClient - REQUEST: http://0.0.0.0:8080/protected/route/digest
[DefaultDispatcher-worker-1] INFO  io.ktor.client.HttpClient - METHOD: HttpMethod(value=GET)
[DefaultDispatcher-worker-1] INFO  io.ktor.client.HttpClient - COMMON HEADERS
[DefaultDispatcher-worker-1] INFO  io.ktor.client.HttpClient - -> Accept: */*
[DefaultDispatcher-worker-1] INFO  io.ktor.client.HttpClient - -> Accept-Charset: UTF-8
[DefaultDispatcher-worker-1] INFO  io.ktor.client.HttpClient - CONTENT HEADERS
[DefaultDispatcher-worker-1] INFO  io.ktor.client.HttpClient - -> Content-Length: 0
[ktor-jetty-8080-1] INFO  ktor.application - 401 Unauthorized: GET - /protected/route/digest
[DefaultDispatcher-worker-1] INFO  io.ktor.client.HttpClient - RESPONSE: 401 Unauthorized
[DefaultDispatcher-worker-1] INFO  io.ktor.client.HttpClient - METHOD: HttpMethod(value=GET)
[DefaultDispatcher-worker-1] INFO  io.ktor.client.HttpClient - FROM: http://0.0.0.0:8080/protected/route/digest
[DefaultDispatcher-worker-1] INFO  io.ktor.client.HttpClient - COMMON HEADERS
[DefaultDispatcher-worker-1] INFO  io.ktor.client.HttpClient - -> Content-Length: 0
[DefaultDispatcher-worker-1] INFO  io.ktor.client.HttpClient - -> WWW-Authenticate: Digest realm="Ktor Server", nonce="ce825e23d3275f40", algorithm="MD5"

这就是客户端客户端立即失败的原因:

Exception in thread "main" io.ktor.client.features.ClientRequestException: Client request(http://0.0.0.0:8080/protected/route/digest) invalid: 401 Unauthorized. Text: ""
        at io.ktor.client.features.DefaultResponseValidationKt$addDefaultResponseValidation.invokeSuspend(DefaultResponseValidation.kt:47)
        at io.ktor.client.features.DefaultResponseValidationKt$addDefaultResponseValidation.invoke(DefaultResponseValidation.kt)
        at io.ktor.client.features.DefaultResponseValidationKt$addDefaultResponseValidation.invoke(DefaultResponseValidation.kt)
        at io.ktor.client.features.HttpCallValidator.validateResponse(HttpCallValidator.kt:54)
        at io.ktor.client.features.HttpCallValidator.access$validateResponse(HttpCallValidator.kt:33)
        at io.ktor.client.features.HttpCallValidator$Companion$install.invokeSuspend(HttpCallValidator.kt:133)
        at io.ktor.client.features.HttpCallValidator$Companion$install.invoke(HttpCallValidator.kt)
        at io.ktor.client.features.HttpCallValidator$Companion$install.invoke(HttpCallValidator.kt)
        at io.ktor.client.features.HttpSend$Feature$install.invokeSuspend(HttpSend.kt:96)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(SuspendFunctionGun.kt:191)
        at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:147)
        at io.ktor.util.pipeline.SuspendFunctionGun.access$loop(SuspendFunctionGun.kt:15)
        at io.ktor.util.pipeline.SuspendFunctionGun$continuation.resumeWith(SuspendFunctionGun.kt:93)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
        at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(SuspendFunctionGun.kt:191)
        at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:147)
        at io.ktor.util.pipeline.SuspendFunctionGun.access$loop(SuspendFunctionGun.kt:15)
        at io.ktor.util.pipeline.SuspendFunctionGun$continuation.resumeWith(SuspendFunctionGun.kt:93)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)

不知道对不对 and/or 跟错误有关.... 但我期望在服务器的header中按照代码“访问'/'路径”而不是[=27]中设置的“领域” =]"Ktor 服务器"

设置服务器时,您缺少领域:

install(Authentication) {

    digest("myDigestAuth") {
        realm = myRealm // This part is missing from your code
        digestProvider { userName, realm ->
            userTable[userName]
        }
    }
}

参考:https://ktor.io/docs/digest.html#configure-provider

否则,服务器将使用默认领域(“Ktor 服务器”),并且客户端没有该领域的凭据。