Ktorサーバーでのフォームベース認証
必要な依存関係: io.ktor:ktor-server-auth
コード例: auth-form-html-dsl, auth-form-session
フォームベース認証は、Webフォームを使用して資格情報(クレデンシャル情報)を収集し、ユーザーを認証します。 KtorでWebフォームを作成するには、HTML DSLを使用するか、FreeMarker、VelocityなどのJVMテンプレートエンジンから選択できます。
フォームベース認証を使用するとユーザー名とパスワードがクリアテキストで渡されるため、機密情報を保護するためにHTTPS/TLSを使用する必要があります。
依存関係の追加
form
認証を有効にするには、ビルドスクリプトにktor-server-auth
アーティファクトを含める必要があります。
フォームベース認証のフロー
フォームベース認証のフローは次のようになります。
- 未認証のクライアントが、サーバーアプリケーション内の特定のルートにリクエストを行います。
- サーバーは、少なくともHTMLベースのWebフォームで構成されるHTMLページを返します。このフォームは、ユーザーにユーザー名とパスワードを要求します。
Ktorでは、Kotlin DSLを使用してフォームを構築できます。また、FreeMarker、VelocityなどのさまざまなJVMテンプレートエンジンから選択することもできます。
- ユーザーがユーザー名とパスワードを送信すると、クライアントはWebフォームデータ(ユーザー名とパスワードを含む)を含むリクエストをサーバーに行います。
POST http://localhost:8080/login
Content-Type: application/x-www-form-urlencoded
username=jetbrains&password=foobar
Ktorでは、ユーザー名とパスワードの取得に使用するパラメーター名を指定する必要があります。
- サーバーはクライアントから送信された資格情報(クレデンシャル)を検証し、要求されたコンテンツで応答します。
フォーム認証のインストール
form
認証プロバイダーをインストールするには、install
ブロック内でform関数を呼び出します。
import io.ktor.server.application.*
import io.ktor.server.auth.*
// ...
install(Authentication) {
form {
// Configure form authentication
}
}
オプションで、指定されたルートを認証するために使用できるプロバイダー名を指定できます。
フォーム認証の設定
ステップ1: フォームプロバイダーの設定
form
認証プロバイダーは、FormAuthenticationProvider.Configクラスを介してその設定を公開します。以下の例では、次の設定が指定されています。
userParamName
プロパティとpasswordParamName
プロパティは、ユーザー名とパスワードの取得に使用されるパラメーター名を指定します。validate
関数は、ユーザー名とパスワードを検証します。validate
関数はUserPasswordCredential
をチェックし、認証が成功した場合はUserIdPrincipal
を返し、認証が失敗した場合はnull
を返します。challenge
関数は、認証が失敗した場合に実行されるアクションを指定します。例えば、ログインページにリダイレクトするか、UnauthorizedResponseを送信できます。
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, "Credentials are not valid")
}
}
}
basic
認証と同様に、UserHashedTableAuthを使用して、ユーザー名とパスワードのハッシュを保持するインメモリテーブルに保存されているユーザーを検証することもできます。
ステップ2: 特定のリソースの保護
form
プロバイダーを設定した後、データが送信されるpost
ルートを定義する必要があります。 次に、このルートを**authenticate**関数内に追加します。 認証が成功した場合、ルートハンドラー内でcall.principal
関数を使用して認証されたUserIdPrincipalを取得し、認証されたユーザーの名前を取得できます。
routing {
authenticate("auth-form") {
post("/login") {
call.respondText("Hello, ${call.principal<UserIdPrincipal>()?.name}!")
}
}
}
ログインしたユーザーのIDを保存するには、セッション認証を使用できます。 例えば、ユーザーがWebフォームを使用して初めてログインするときに、ユーザー名をクッキーセッションに保存し、その後のリクエストでsession
プロバイダーを使用してそのユーザーを認証できます。