Ktor 서버의 폼 기반 인증
필수 의존성: io.ktor:ktor-server-auth
코드 예시: auth-form-html-dsl, auth-form-session
폼 기반 인증은 웹 폼을 사용하여 자격 증명 정보를 수집하고 사용자를 인증합니다. Ktor에서 웹 폼을 만들려면, HTML DSL을 사용하거나 FreeMarker, Velocity 등과 같은 JVM 템플릿 엔진 중에서 선택할 수 있습니다.
폼 기반 인증을 사용할 때 사용자 이름과 비밀번호가 일반 텍스트로 전달되므로, 민감한 정보를 보호하려면 HTTPS/TLS를 사용해야 합니다.
의존성 추가
form
인증을 활성화하려면 빌드 스크립트에 ktor-server-auth
아티팩트를 포함해야 합니다.
폼 기반 인증 흐름
폼 기반 인증 흐름은 다음과 같습니다:
인증되지 않은 클라이언트가 서버 애플리케이션의 특정 경로로 요청을 보냅니다.
서버는 사용자 이름과 비밀번호를 요구하는 HTML 기반 웹 폼으로 구성된 HTML 페이지를 반환합니다.
Ktor는 Kotlin DSL을 사용하여 폼을 만들거나, FreeMarker, Velocity 등과 같은 다양한 JVM 템플릿 엔진 중에서 선택할 수 있도록 합니다.
사용자가 사용자 이름과 비밀번호를 제출하면, 클라이언트는 웹 폼 데이터(사용자 이름과 비밀번호 포함)를 담은 요청을 서버로 보냅니다.
kotlinPOST 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를 저장하기 위해 세션 인증을 사용할 수 있습니다. 예를 들어, 사용자가 웹 폼을 사용하여 처음 로그인할 때, 사용자 이름을 쿠키 세션에 저장하고 이후 요청에서는 session
프로바이더를 사용하여 이 사용자를 인증할 수 있습니다.