代码之家  ›  专栏  ›  技术社区  ›  Izbassar Tolegen

如何在Kotlin的Ktor中提取访问权限验证

  •  0
  • Izbassar Tolegen  · 技术社区  · 5 年前

    jwt 令牌作为身份验证。然后我必须限制特定角色的某些路由。为此,我正在创建principal,其中包含相关信息:

    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)
            }
          }
        }
      }
    }
    

    userId roleId 在对正确登录的用户进行签名时提供。现在我可以这样限制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)
      }
    }
    

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

    0 回复  |  直到 5 年前
        1
  •  1
  •   avolkmann    5 年前

    您可以在 validate 封锁。

    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)
        }
    }
    

    顺便说一下,你发布的代码有几个问题,所以它不会编译。