【问题标题】:How to extract access rights validation in Kotlin's Ktor如何在 Kotlin 的 Ktor 中提取访问权限验证
【发布时间】:2019-10-11 11:49:46
【问题描述】:

我有基于 Ktor 的 REST API 应用程序,它使用 jwt 令牌作为身份验证。然后我必须为特定角色限制某些路线。为了做到这一点,我正在创建包含相关信息的主体:

data class UserPrincipal (
  val id: Long,
  val username: String,
  val roleId: Long,
): Princpal {
  override fun getName() = username
}

object AuthLogin {
  fun Application.auth(jwt: JwtProvider) {
    install(Authentication) {
      jwt("jwt") {
        realm = jwt.realm()
        verifier(jwt.verifier())
        validate {
          val userId = it.payload.getClaim("id").asLong()
          val username = it.payload.getClain("name")
          val roleId = it.payload.getClaim("roleId").asLong()
          UserPrincipal(userId, username, roleId)
        }
      }
    }
  }
}

在为正确登录的用户签名时,会提供带有 userIdroleId 的声明。现在我可以像这样限制 REST 端点:

object RestModule {
  fun Application.enititiesOne(userRepo: UserRepo) {
    routing {
      authenticate("jwt") {
        route("/entities1") {
          get {
            val principal = call.principal<UserPrincipal>()
            when(userRepo.hasAccessByRole(principal!!.roleId, "CAN_R_E1") {
              false -> call.respond(HttpStatusCode.Forbidden)
              true -> // some retrieval logic
          }
          post {
            val principal = call.principal<UserPrincipal>()
            when(userRepo.hasAccessByRole(principal!!.roleId, "CAN_W_E1") {
              false -> call.respond(HttpStatusCode.Forbidden)
              true -> // some update logic
          }
        }
      }
    }
  }
}

正如您所见,即使在一个路由函数中,我也必须复制两次检查主体角色的代码。我可以将其移出以运行,但我想要的是一个定义我的安全角色的地方。类似的东西:

authenticate {
  val principal = call.principal<UserPrincipal()
  val rights = userRepo.rightsByRole(principal.roleId)
  when(routes) {
    get("/entities1/**") -> 
      if(rights.contain("CAN_R_E1")) call.proceed
      else call.respond(HttpStatusCode.Forbidden)
    post("/entites1) -> rights.contain("CAN_W_E1") // similar 
    get("/entities2/**") -> rights.contain("CAN_R_E2") // similar
    else -> call.respond(401)
  }
}

然后将其插入其余端点。或者我可以在 Kotlin 的 Ktor 中使用一些类似的方法吗?似乎拦截器是我需要的,但我不确定如何以预期的方式使用它们。

【问题讨论】:

  • 您可以在安装块中创建单独的身份验证配置。然后相应地包装路线。此外,您可能可以检查验证块中的路由 url / 动词,以自动执行此操作。

标签: kotlin ktor


【解决方案1】:

您可以在validate 块中查看方法和uri。

install(Authentication) {
    jwt {
        validate {
            val userId = it.payload.getClaim("id").asLong()
            val username = it.payload.getClaim("name").asString()
            val roleId = it.payload.getClaim("roleId").asLong()
            UserPrincipal(userId, username, roleId)
            val requiredRole = when (request.httpMethod) {
                HttpMethod.Get -> // get role
                HttpMethod.Post -> // get other role
            }
            // check if role exists in repo
        }
    }
}
install(Routing) {
    get {
        val principal = call.principal<UserPrincipal>()!!
        call.respond(principal)
    }

    post {
        val principal = call.principal<UserPrincipal>()!!
        call.respond(principal)
    }
}

顺便说一句,您发布的代码存在几个问题,因此无法编译。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-05
    • 2022-01-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多