kotlin Ktor中的可选路由身份验证

fnatzsnv  于 2023-03-30  发布在  Kotlin
关注(0)|答案(2)|浏览(166)

我在我的Ktor应用程序中有一个路由,我想选择性地进行身份验证。最好的方法是什么?如果我放入两个路由块,两个调用都默认为未经身份验证的一个。
例如

routing {
        post("/my-route") {
            val request = call.receive<MyRouteRequest>()
            ...
        }
        authenticate(Constants.myAuthScope) {
            post("/my-route") {
                val request = call.receive<MyRouteRequest>()
                val user = call.principal<User>()
                ...
            }
      }
hujrc8aj

hujrc8aj1#

应该可以使用更明确的模型,并结合对路由或底层服务中的模型进行验证(取决于这被视为域逻辑还是API逻辑)
对于基本auth,它看起来有点像:

sealed interface PrincipalResult {
    data class User(/* ... */): PrincipalResult

    object NoUserProvided: PrincipalResult

    // This might be replaced with a null result to conform with the Ktor API
    // I prefer making it explicit and communicate what's going on
    // and not just accept a null that means everything and nothing.
    //
    // This can also be made into a data class and expanded
    // with additional information, allowing for better errors and richer debugging
    object InvalidUserCredentials: PrincipalResult
}
install(Authentication) {
    basic("stuart-auth") {
        realm = "Access to the '/' path"
        validate { credentials ->
            if (credentials.isMissing()) {
                PrincipalResult.NoUserProvided
            } else if (credentials.isValid() {
                PrincipalResult.User(/* ... */)
            } else {
                PrincipalResult.InvalidUserCredentials
            }
        }
    }
}

现在可以做到:

authenticate(Constants.myAuthScope) {
    post("/my-route") {
        val request = call.receive<MyRouteRequest>()
        val principalResult = call.principal<PrincipalResult>()

        when (principalResult) {
            is PrincipalResult.User ->
            is PrincipalResult.NoUserProvided ->
            is PrincipalResult.InvalidUserCredentials ->
        }
        // ...
    }
}

当然,这种模式应该应用于您实际使用的任何身份验证方案,例如JWT,OAuth,LDAP等。

g52tjvyc

g52tjvyc2#

尝试authenticateoptional参数,如

authenticate(Constants.myAuthScope, optional = true) {
    post("/my-route") {}
}

相关问题