У меня есть защищенный ресурс в KTOR, который требует аутентификации через сеанс аутентификации.
authenticate("auth-session") {
get("/list") {...}
route("/login") {
get { call.respond(FreeMarkerContent("login.ftl", model = null)) }
authenticate("auth-form") {
post {
val loginUser = call.principal<UserIdPrincipal>()?.name.toString()
val session = UserSession(loginUser, AccessLevel.USER )
call.sessions.set(session)
call.respondRedirect("/")
}
}
Можно ли захватить исходный ресурс (т. е. «/list») и перенаправить его обратно вместо «/»? У меня есть другие ресурсы, защищенные сеансом аутентификации, и все они требуют разных URI перенаправления. Я ценю помощь, так как не смог найти решения в другом месте.
Я пытался захватить заголовок реферера, но он теряется после операций получения/отправки.
Вы можете передать исходный запрошенный URL-адрес на маршрут /login
POST через параметр запроса. В вызове провайдера аутентификации сеанса клиент может быть перенаправлен на страницу /login
с параметром запроса, который затем можно вставить в действие формы в шаблоне login.ftl
. Если аутентификация прошла успешно, значение параметра запроса можно использовать для окончательного перенаправления. Вот полный фрагмент кода:
import freemarker.cache.ClassTemplateLoader
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.auth.*
import io.ktor.server.engine.*
import io.ktor.server.freemarker.*
import io.ktor.server.netty.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.server.sessions.*
fun main() {
embeddedServer(Netty, port = 8080) {
install(FreeMarker) {
templateLoader = ClassTemplateLoader(this::class.java.classLoader, "templates")
}
install(Sessions) {
cookie<UserSession>("user_session") {
cookie.path = "/"
cookie.maxAgeInSeconds = 60
}
}
install(Authentication) {
session<UserSession>("auth-session") {
validate { session ->
if (session.name.startsWith("jet")) {
session
} else {
null
}
}
challenge {
call.respondRedirect("/login?origin=${call.request.uri}")
}
}
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")
}
}
}
routing {
authenticate("auth-session") {
get("/list") { call.respondText { "List" } }
}
route("/login") {
get { call.respond(FreeMarkerContent("login.ftl", model = mapOf("origin" to call.request.queryParameters["origin"]))) }
authenticate("auth-form") {
post {
val loginUser = call.principal<UserIdPrincipal>()?.name.toString()
val session = UserSession(loginUser)
call.sessions.set(session)
val origin = call.request.queryParameters["origin"]
if (!origin.isNullOrBlank()) {
call.respondRedirect(origin)
return@post
}
call.respondRedirect("/")
}
}
}
}
}.start(wait = true)
}
data class UserSession(val name: String) : Principal
login.ftl
:
<html>
<body>
<form action = "/login?origin=${origin}" method = "post">
<input type = "text" name = "username" value = "jetbrains">
<input type = "password" name = "password" value = "foobar">
<input type = "submit">
</form>
</body>
</html>