Skip to content

Ktor 伺服器中的表單式身份驗證

所需依賴項: io.ktor:ktor-server-auth

程式碼範例: auth-form-html-dsl, auth-form-session

原生伺服器
Ktor 支援 Kotlin/Native,並且允許您在沒有額外運行時或虛擬機器的情況下運行伺服器。
支援: ✅

表單式身份驗證使用網頁表單來收集憑證資訊並驗證使用者。要在 Ktor 中建立網頁表單,您可以使用 HTML DSL 或選擇 JVM 模板引擎,例如 FreeMarker、Velocity 等。

考慮到使用表單式身份驗證時,使用者名稱和密碼是以明文形式傳遞的,您需要使用 HTTPS/TLS 來保護敏感資訊。

新增依賴項

要啟用 form 身份驗證,您需要在建構腳本中包含 ktor-server-auth artifact:

Kotlin
Groovy
XML

表單式身份驗證流程

表單式身份驗證流程可能如下所示:

  1. 未經身份驗證的客戶端向伺服器應用程式中的特定 路由 發出請求。

  2. 伺服器返回一個 HTML 頁面,該頁面至少包含一個基於 HTML 的網頁表單,提示使用者輸入使用者名稱和密碼。

    Ktor 允許您使用 Kotlin DSL 建立表單,或者您可以選擇各種 JVM 模板引擎,例如 FreeMarker、Velocity 等。

  3. 當使用者提交使用者名稱和密碼時,客戶端會向伺服器發出一個包含網頁表單資料 (其中包括使用者名稱和密碼) 的請求。

    kotlin
    POST http://localhost:8080/login
    Content-Type: application/x-www-form-urlencoded
    
    username=jetbrains&password=foobar

    在 Ktor 中,您需要 指定參數名稱 以用於獲取使用者名稱和密碼。

  4. 伺服器 驗證 客戶端發送的憑證,並回應所請求的內容。

安裝表單身份驗證

要安裝 form 身份驗證提供者,請在 install 區塊內呼叫 form 函數:

kotlin
import io.ktor.server.application.*
import io.ktor.server.auth.*
// ...
install(Authentication) {
    form {
        // 配置表單身份驗證
    }
}

您可以選擇指定一個 提供者名稱,該名稱可用於 驗證指定的路由

配置表單身份驗證

步驟 1:配置表單提供者

form 身份驗證提供者透過 FormAuthenticationProvider.Config 類別暴露其設定。在下面的範例中,指定了以下設定:

  • userParamNamepasswordParamName 屬性指定了用於獲取使用者名稱和密碼的參數名稱。
  • validate 函數驗證使用者名稱和密碼。 validate 函數檢查 UserPasswordCredential,並在成功身份驗證時返回一個 UserIdPrincipal,或者在身份驗證失敗時返回 null
  • challenge 函數指定了身份驗證失敗時執行的操作。例如,您可以重定向回登入頁面或發送 UnauthorizedResponse
kotlin
install(Authentication) {
    form("auth-form") {
        userParamName = "username"
        passwordParamName = "password"
        validate { credentials ->
            if (credentials.name == "jetbrains" && credentials.password == "foobar") {
                UserIdPrincipal(credentials.name)
            } else {
                null
            }
        }
        challenge {
            call.respond(HttpStatusCode.Unauthorized, "憑證無效")
        }
    }
}

至於 basic 身份驗證,您也可以使用 UserHashedTableAuth 來驗證儲存在記憶體表格中的使用者,該表格儲存使用者名稱和密碼雜湊。

步驟 2:保護特定資源

配置 form 提供者後,您需要定義一個 post 路由來接收資料。 然後,在 authenticate 函數內部新增此路由。 在成功身份驗證的情況下,您可以使用 call.principal 函數在路由處理器內部檢索已驗證的 UserIdPrincipal,並獲取已驗證使用者的名稱。

kotlin
routing {
    authenticate("auth-form") {
        post("/login") {
            call.respondText("哈囉,${call.principal<UserIdPrincipal>()?.name}!")
        }
    }
}

您可以使用 Session 身份驗證 來儲存登入使用者的 ID。 例如,當使用者首次使用網頁表單登入時,您可以將使用者名稱儲存到一個 cookie session 中,並在後續請求中,使用 session 提供者來授權該使用者。