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 { ... }
}
}
如何在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 { ... }
}
}