ktor框架如何限制路由访问?

How to restrict route access in ktor framework?

如何在ktor框架中限制route访问?

//only admin           
post("/add") {
   call.respondText { "add" }
}

post("/delete") {
   call.respondText { "delete" }
}
        

您可以编写一个方法来创建一个仅允许管理员访问的路由。在该方法内部,拦截新创建的路由以注入验证代码。在以下示例中,如果 header admin 的值为 1,则管理员发出请求,否则 /add/delete 路由响应401 Unauthorized 状态将被返回。

import io.ktor.application.*
import io.ktor.auth.*
import io.ktor.http.*
import io.ktor.request.*
import io.ktor.response.*
import io.ktor.routing.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.util.pipeline.*

fun main() {
    embeddedServer(Netty, port = 5555, host = "0.0.0.0") {
        routing {
            admin {
                post("/add") {
                    call.respondText { "add" }
                }

                post("/delete") {
                    call.respondText { "delete" }
                }
            }

            post("/show") {
                call.respondText { "show" }
            }
        }
    }.start(wait = false)
}

private val validationPhase = PipelinePhase("Validate")

fun Route.admin(build: Route.() -> Unit): Route {
    val route = createChild(AdminSelector())

    route.insertPhaseAfter(ApplicationCallPipeline.Features, Authentication.ChallengePhase)
    route.insertPhaseAfter(Authentication.ChallengePhase, validationPhase)
    route.intercept(validationPhase) {
        if (!isAdmin(call.request)) {
            call.respond(HttpStatusCode.Forbidden)
            finish()
        }
    }
    route.build()
    return route
}

class AdminSelector: RouteSelector() {
    override fun evaluate(context: RoutingResolveContext, segmentIndex: Int) = RouteSelectorEvaluation.Transparent
}

fun isAdmin(request: ApplicationRequest): Boolean {
    return request.headers["admin"] == "1"
}

对于 Ktor 2.x,Alexsei 提出的解决方案不再适用,因为 ChallengePhase 现在被标记为 internal,因为他们完全重组了插件系统。

这个代码片段似乎对我有用。

fun Route.authorization(build: Route.() -> Unit): Route {
    val route = createChild(CustomSelector())
    val plugin = createRouteScopedPlugin("CustomAuthorization") {
        on(AuthenticationChecked) { call ->
            val principal = call.authentication.principal
            // custom logic
        }
    }
    route.install(plugin)
    route.build()
    return route
}

private class CustomSelector : RouteSelector() {
    override fun evaluate(context: RoutingResolveContext, segmentIndex: Int) = RouteSelectorEvaluation.Transparent
}

当然,您可以在函数中添加参数来指定所需角色等限制。

要确保路线...

fun Route.myRoute() = route("test") {
    authorization {
        get { ... }
    }
}

更多详情:https://ktor.io/docs/custom-plugins.html