在 Ktor 中将身份验证与 RateLimit 结合使用的最佳方法是什么?

问题描述 投票:0回答:1

我想在我的应用程序中支持三种类型的请求:

  • 访客访问:没有
    Authorization
    标头的请求。
  • 自定义令牌访问:带有
    Authorization: Token {token}
    标头的请求。我需要定义一个自定义机制来将令牌映射到 AuthUser。
  • JWT 令牌访问:带有
    Authorization: Bearer {jwt}
    标头的请求。

每种类型的请求对应不同的速率限制:

  • 访客访问:最低速率限制。
  • JWT 代币访问:更高的速率限制。
  • 自定义令牌访问:无速率限制。

在 Ktor 中实现此设置的最佳方法是什么?

我尝试使用

authenticate
来保护特定资源,但我遇到了 来宾访问 端点的问题。具体来说,当请求包含
Authorization
标头时,
call.authentication.principal()
仍返回
null

或者,我可以对所有请求应用身份验证。但是,我不确定如何正确实施这种方法。

如何配置身份验证来处理所有请求类型(访客、自定义令牌、JWT)并为每种情况应用适当的速率限制?

authentication {
    jwt {
            authHeader { call ->
                val header = call.request.headers["Authorization"]
                if (header.isNullOrBlank()) {
                    return@authHeader HttpAuthHeader.Single("NoAuth", "")
                }
                if (header.startsWith("Bearer ")) {
                    return@authHeader HttpAuthHeader.Single("Bearer", header.removePrefix("Bearer "))
                } else {
                    return@authHeader HttpAuthHeader.Single("Token", header.removePrefix("Bot "))
                }
            }
            verifier { header ->
                val scheme = header.authScheme
                return@verifier when (scheme) {
                    "Bearer" -> Jwt.userVerifier
                    "Token" -> TODO("")
                    else -> TODO("")
                }
            }

            validate {
                println(it.payload.toString())
                return@validate AuthUser(role = AuthUser.Role.NoLogin)
            }
            challenge { _, _ ->
                call.respond(DataVo(401, "Unauthorized", null))
            }
        }
    }
}
// reat limit
install(RateLimit) {
    register {
        requestKey { call ->
            val headers = call.request.headers
            headers["X-Real-IP"] ?: headers["X-Forwarded-For"] ?: call.request.origin.remoteHost
        }
        rateLimiter(limit = 6000, refillPeriod = 1.minutes)

        requestWeight { call, _ ->
            val user = call.principal<AuthUser>()
            when {
                // no header Authorization
                user == null || !user.isLogin() -> 20
                // Authorization: Token 
                user.isAdmin() -> 0
                // Authorization: Bearer
                else -> 8
            }
        }
    }
}
ktor
1个回答
0
投票

据我所知,目前这是不可能的。 我已经在here提出了一个关于此问题的问题。

© www.soinside.com 2019 - 2024. All rights reserved.