Ktor Server 中的会话认证
必需的依赖项: io.ktor:ktor-server-auth
, io.ktor:ktor-server-sessions
代码示例: auth-form-session
会话 提供了一种在不同 HTTP 请求之间持久化数据的机制。典型的用例包括存储已登录用户的 ID、购物车的内容,或者在客户端保留用户偏好设置。
在 Ktor 中,已经拥有关联会话的用户可以使用 session
提供程序进行认证。例如,当用户首次使用 web 表单 登录时,你可以将用户名保存到 cookie 会话中,并在后续请求中使用 session
提供程序授权该用户。
你可以在 Ktor Server 中的认证与授权 部分获取关于 Ktor 中认证和授权的通用信息。
添加依赖项
为了启用 session
认证,你需要将以下 artifact 包含在构建脚本中:
添加
ktor-server-sessions
依赖项用于使用会话:KotlinGroovyXML添加
ktor-server-auth
依赖项用于认证:KotlinGroovyXML
会话认证流程
带有会话的认证流程可能会有所不同,取决于用户在你的应用程序中如何被认证。让我们看看它在 基于表单的认证 中会是什么样子:
- 客户端向服务器发出包含 web 表单数据(包括用户名和密码)的请求。
- 服务器验证客户端发送的凭据,将用户名保存到 cookie 会话中,并响应请求的内容以及一个包含用户名的 cookie。
- 客户端使用 cookie 向受保护的资源发出后续请求。
- 根据收到的 cookie 数据,Ktor 检测此用户是否存在 cookie 会话,并且,可选地,对收到的会话数据执行额外的验证。在验证成功的情况下,服务器响应请求的内容。
安装会话认证
为了安装 session
认证提供程序,请在 install
代码块内调用 session 函数,并传入所需的会话类型:
import io.ktor.server.application.*
import io.ktor.server.auth.*
import io.ktor.server.sessions.*
//...
install(Authentication) {
session<UserSession> {
// 配置会话认证
}
}
配置会话认证
本节演示了如何使用 基于表单的认证 认证用户,将此用户的信息保存到 cookie 会话中,然后在使用 session
提供程序的后续请求中授权该用户。
有关完整示例,请参见 auth-form-session。
步骤 1:创建数据类
首先,你需要创建一个数据类用于存储会话数据:
@Serializable
data class UserSession(val name: String, val count: Int)
步骤 2:安装并配置会话
创建数据类后,你需要安装并配置 Sessions
插件。以下示例安装并配置了一个 cookie 会话,带有指定的 cookie 路径和过期时间。
cookie<UserSession>("user_session") {
cookie.path = "/"
cookie.maxAgeInSeconds = 60
}
}
要了解更多关于配置会话的信息,请参见 会话配置概述。
步骤 3:配置会话认证
session
认证提供程序通过 SessionAuthenticationProvider.Config
类公开其设置。在以下示例中,指定了以下设置:
validate()
函数检测 会话实例,并在认证成功的情况下返回Any
类型的 principal。challenge()
函数指定了认证失败时执行的操作。例如,你可以重定向回登录页面或发送一个UnauthorizedResponse
。
install(Authentication) {
session<UserSession>("auth-session") {
validate { session ->
if(session.name.startsWith("jet")) {
session
} else {
null
}
}
challenge {
call.respondRedirect("/login")
}
}
}
步骤 4:在会话中保存用户数据
要将已登录用户的信息保存到会话中,请使用 call.sessions.set()
函数。
以下示例展示了一个使用 web 表单的简单认证流程:
authenticate("auth-form") {
post("/login") {
val userName = call.principal<UserIdPrincipal>()?.name.toString()
call.sessions.set(UserSession(name = userName, count = 1))
call.respondRedirect("/hello")
}
}
有关基于表单的认证流程的更多详细信息,请参考 基于表单的认证 文档。
步骤 5:保护特定资源
配置 session
提供程序后,你可以在你的应用程序中使用 authenticate()
函数保护特定资源。
认证成功后,你可以通过在路由处理程序内使用 call.principal()
函数来检索已认证的 principal(在这种情况下,是 UserSession
实例):
authenticate("auth-session") {
get("/hello") {
val userSession = call.principal<UserSession>()
call.sessions.set(userSession?.copy(count = userSession.count + 1))
call.respondText("Hello, ${userSession?.name}! Visit count is ${userSession?.count}.")
}
}
有关完整示例,请参见 auth-form-session。