在KTOR客户端中重新攻击loadTokens的正确方法

发布于 2025-01-25 07:59:10 字数 1786 浏览 5 评论 0原文

在我的移动应用程序中,我有一个Singleton KTOR httpclient带有以下配置的承载身份验证:

HttpClient(…) {
    install(Auth) {
        bearer {
            sendWithoutRequest { requestBuilder -> some condition }
            loadTokens(tokensStorage::getTokens)
            refreshTokens {
                performTokenRefresh(oldTokens.refreshToken)
            }
        }
    }
}

现在考虑以下流程:

  1. 用户在我的tokenstorage中存储的令牌时打开应用程序 。无效。
  2. httpclienttokenstorage加载令牌,并且请求以401失败。
  3. httpclient试图执行刷新,但也会失败,因为它刷新了,令牌无效。
  4. 将用户重定向到登录页面,登录,新有效令牌存储在TokenStorage中。
  5. 现在,从应用程序中,用户可以在第2-3点重试呼叫。但是,这将永远失败,直到应用程序关闭为止,因为httpclient再也不会尝试调用loadTokens。实际上,据我从源代码中看到,loadTokens仅被调用一次,然后再也不会被调用。

我发现了一些解决问题的方法。

第一个是从httpclient中手动检索bearerauthprovider,并清除以下片段中的令牌,但似乎是一个hacky的解决方法:

httpClient.plugin(Auth).providers
    .filterIsInstance<BearerAuthProvider>()
    .first().clearToken()

另一个是手动加载当前令牌来自我的tokenStorage refreshtoken ,而无视[email&nbsp; nbsp; procected] code> </

refreshTokens {
    val currentRefreshToken = tokenStorage.getTokens().refreshToken
    performTokenRefresh(currentRefreshToken)
}

>登录)。

所以我的问题是:是否有一种更干净的方法来处理这种情况?我在滥用KTOR吗?

In my mobile app, I have a singleton Ktor HttpClient with bearer authentication configured as such:

HttpClient(…) {
    install(Auth) {
        bearer {
            sendWithoutRequest { requestBuilder -> some condition }
            loadTokens(tokensStorage::getTokens)
            refreshTokens {
                performTokenRefresh(oldTokens.refreshToken)
            }
        }
    }
}

Now consider the following flow:

  1. The user opens the app while the tokens stored in my tokenStorage are not valid.
  2. The HttpClient loads the tokens from tokenStorage and the request fails with a 401.
  3. The HttpClient tries to perform a refresh but it fails too because the refresh token is invalid.
  4. The user is redirected to the login page, logs in, and the new valid tokens are stored in tokenStorage.
  5. Now from the app the user can retry the call that failed in points 2-3. However this will fail forever until the app is closed, because the HttpClient never tries to call loadTokens anymore. Indeed, as far as I can see from the source code, loadTokens is called only once and then never again.

I found out a couple of ways to solve the issue.

The first one is to manually retrieve BearerAuthProvider from the HttpClient and clear the token myself like in the following snippet, but it seems like a hacky workaround:

httpClient.plugin(Auth).providers
    .filterIsInstance<BearerAuthProvider>()
    .first().clearToken()

Another one is to manually load the current token from my tokenStorage in refreshToken and disregard what get passed in [email protected]:

refreshTokens {
    val currentRefreshToken = tokenStorage.getTokens().refreshToken
    performTokenRefresh(currentRefreshToken)
}

However this means that the client will do an unnecessary call to the refresh API, while having already a valid token pair (obtained from the login).

So my question is: is there a cleaner way to handle the situation? Am I misusing Ktor?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

秋叶绚丽 2025-02-01 07:59:10

我们在两个地方手动清除它:
我们有“注销”用例,无论用户手动注销还是401踢出,它将始终触发。因为我们还需要清除其他缓存数据。
因此,该注销用例的第一行是通知HTTP客户端的,它的模具所缓存不再有效。

fun invalidateAuthTokens() {

    val authProvider = httpClient.authProvider<BearerAuthProvider>()

    requireNotNull(authProvider)

    authProvider.clearToken()
}

您必须确保将其调用。
当我们可以通过应用程序链接打开登录屏幕时,我们面临着案例,因此可能是用户正在记录的时候,而其他用户仍被记录 HTTP客户端具有空的令牌,并且不知道它们是无效的。
在这种情况下,我们还需要清除登录时的缓存,因此KTOR的LoadTokens {}在需要时再次致电。

We clear it manually in 2 places:
We have the "Logout" use case which will be always triggered no matter if user logout manually or by 401 kick out. Because we need to clear other cached data as well.
So the first lines of that logout use case is to notify the http client that whatever tokens it cached are not valid anymore.

fun invalidateAuthTokens() {

    val authProvider = httpClient.authProvider<BearerAuthProvider>()

    requireNotNull(authProvider)

    authProvider.clearToken()
}

You must make sure it will be called.
We faced the case when we can open Login screen via app links, so potentially a user is logging while other user is still logged or the http client has empty tokens and doesn't know they are not valid.
In that case we also needed to clear the cache on Login, so ktor's loadTokens{} called again when needed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文