Ktor 서버의 다이제스트 인증
필수 의존성: io.ktor:ktor-server-auth
코드 예시: auth-digest
다이제스트(Digest) 인증 방식은 접근 제어 및 인증에 사용되는 HTTP 프레임워크의 일부입니다. 이 방식에서는 사용자 이름과 비밀번호를 네트워크를 통해 전송하기 전에 해시 함수를 적용합니다.
Ktor는 다이제스트 인증을 사용하여 사용자 로그인 및 특정 라우트를 보호할 수 있도록 지원합니다. Ktor에서의 인증에 대한 일반적인 정보는 Ktor 서버에서의 인증 및 인가 섹션에서 확인할 수 있습니다.
의존성 추가
digest
인증을 활성화하려면 빌드 스크립트에 ktor-server-auth
아티팩트를 포함해야 합니다.
다이제스트 인증 흐름
다이제스트 인증 흐름은 다음과 같습니다.
클라이언트가 서버 애플리케이션의 특정 라우트에
Authorization
헤더 없이 요청합니다.서버는 클라이언트에
401
(Unauthorized) 응답 상태로 응답하고,WWW-Authenticate
응답 헤더를 사용하여 다이제스트 인증 방식이 라우트를 보호하는 데 사용된다는 정보를 제공합니다. 일반적인WWW-Authenticate
헤더는 다음과 같습니다.WWW-Authenticate: Digest realm="Access to the '/' path", nonce="e4549c0548886bc2", algorithm="MD5"
Ktor에서는
digest
인증 제공자를 구성할 때 realm과 nonce 값을 생성하는 방법을 지정할 수 있습니다.일반적으로 클라이언트는 사용자가 자격 증명을 입력할 수 있는 로그인 대화 상자를 표시합니다. 그런 다음 클라이언트는 다음
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)
서버는 클라이언트가 보낸 자격 증명을 검증하고 요청된 콘텐츠로 응답합니다.
다이제스트 인증 설치
digest
인증 제공자를 설치하려면 install
블록 내에서 digest 함수를 호출합니다.
import io.ktor.server.application.*
import io.ktor.server.auth.*
// ...
install(Authentication) {
digest {
// Configure digest authentication
}
}
선택적으로 지정된 라우트를 인증하는 데 사용될 수 있는 제공자 이름을 지정할 수 있습니다.
다이제스트 인증 구성
Ktor에서 다양한 인증 제공자를 구성하는 방법에 대한 일반적인 아이디어를 얻으려면 인증 구성을 참조하세요. 이 섹션에서는 digest
인증 제공자의 구성 세부 정보를 살펴보겠습니다.
1단계: 다이제스트가 포함된 사용자 테이블 제공
digest
인증 제공자는 다이제스트 메시지의 HA1
부분을 사용하여 사용자 자격 증명을 검증합니다. 따라서 사용자 이름과 해당 HA1
해시를 포함하는 사용자 테이블을 제공할 수 있습니다. 아래 예시에서는 getMd5Digest
함수가 HA1
해시를 생성하는 데 사용됩니다.
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에 매핑할 수 있도록 합니다.
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을 검색하고 인증된 사용자의 이름을 가져올 수 있습니다.
routing {
authenticate("auth-digest") {
get("/") {
call.respondText("Hello, ${call.principal<CustomPrincipal>()?.userName}!")
}
}
}