Skip to content

Ktor Server 中的摘要认证

必需的依赖项: io.ktor:ktor-server-auth

代码示例: auth-digest

原生服务器
Ktor 支持 Kotlin/Native,允许您无需额外的运行时或虚拟机即可运行服务器。
支持: ✖️

摘要认证方案是 HTTP 框架的一部分,用于访问控制和认证。在此方案中,在通过网络发送用户名和密码之前,会对其应用哈希函数。

Ktor 允许您使用摘要认证来登录用户和保护特定的路由。您可以在 Ktor Server 中的认证与授权章节中获取有关 Ktor 认证的一般信息。

添加依赖项

要启用 digest 认证,您需要在构建脚本中包含 ktor-server-auth 构件:

Kotlin
Groovy
XML

摘要认证流程

摘要认证流程如下所示:

  1. 客户端向服务器应用程序中的特定路由发起不带 Authorization 请求头的请求。

  2. 服务器向客户端响应 401 (Unauthorized) 响应状态,并使用 WWW-Authenticate 响应头提供信息,表明该路由使用了摘要认证方案。一个典型的 WWW-Authenticate 头如下所示:

    WWW-Authenticate: Digest
            realm="Access to the '/' path",
            nonce="e4549c0548886bc2",
            algorithm="MD5"

    在 Ktor 中,您可以在配置 digest 认证提供者时指定 realm 和生成 nonce 值的方式。

  3. 通常,客户端会显示一个登录对话框,用户可以在其中输入凭据。然后,客户端发起一个带有以下 Authorization 请求头的请求:

    Authorization: Digest username="jetbrains",
            realm="Access to the '/' path",
            nonce="e4549c0548886bc2",
            uri="/",
            algorithm=MD5,
            response="6299988bb4f05c0d8ad44295873858cf"

    response 值通过以下方式生成:

    a. HA1 = MD5(username:realm:password)

    这部分存储在服务器上,Ktor 可以用它来验证用户凭据。

    b. HA2 = MD5(method:digestURI)

    c. response = MD5(HA1:nonce:HA2)

  4. 服务器验证客户端发送的凭据并响应所请求的内容。

安装摘要认证

要安装 digest 认证提供者,请在 install 代码块中调用 digest 函数:

kotlin
import io.ktor.server.application.*
import io.ktor.server.auth.*
// ...
install(Authentication) {
    digest {
        // Configure digest authentication
    }
}

您可以选择性地指定一个提供者名称,该名称可用于认证指定的路由

配置摘要认证

要大致了解如何在 Ktor 中配置不同的认证提供者,请参阅配置认证。在本节中,我们将重点介绍 digest 认证提供者的配置细节。

步骤 1:提供包含摘要的用户表

digest 认证提供者使用摘要消息的 HA1 部分来验证用户凭据。因此,您可以提供一个包含用户名和对应的 HA1 哈希值的用户表。在下面的示例中,getMd5Digest 函数用于生成 HA1 哈希值:

kotlin
fun getMd5Digest(str: String): ByteArray = MessageDigest.getInstance("MD5").digest(str.toByteArray(UTF_8))

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

步骤 2:配置摘要提供者

digest 认证提供者通过 DigestAuthenticationProvider.Config 类公开其设置。在下面的示例中,指定了以下设置:

  • realm 属性设置要传递到 WWW-Authenticate 请求头中的 realm。
  • digestProvider 函数获取指定用户名的摘要的 HA1 部分。
  • (可选) validate 函数允许您将凭据映射到自定义 Principal。
kotlin
fun Application.main() {
    install(Authentication) {
        digest("auth-digest") {
            realm = myRealm
            digestProvider { userName, realm ->
                userTable[userName]
            }
            validate { credentials ->
                if (credentials.userName.isNotEmpty()) {
                    CustomPrincipal(credentials.userName, credentials.realm)
                } else {
                    null
                }
            }
        }
    }
}

data class CustomPrincipal(val userName: String, val realm: String)

您还可以使用 nonceManager 属性来指定如何生成 nonce 值。

步骤 3:保护特定资源

配置 digest 提供者后,您可以使用 authenticate 函数保护应用程序中的特定资源。如果认证成功,您可以在路由处理程序中使用 call.principal 函数检索经过认证的 Principal,并获取认证用户的名称。

kotlin
routing {
    authenticate("auth-digest") {
        get("/") {
            call.respondText("Hello, ${call.principal<CustomPrincipal>()?.userName}!")
        }
    }
}