【问题标题】:OkHttp Interceptor chain broken when getting token获取令牌时,OkHttp 拦截器链断开
【发布时间】:2019-10-28 23:50:09
【问题描述】:

我有一个 OkHttp 拦截器,当请求收到 401 HTTP 错误时,它应该请求令牌。现在,登录服务的请求已经完成,但是链被破坏并且原始请求没有重试。 下面是我的拦截器的拦截方法:

override fun intercept(chain: Interceptor.Chain): Response {
        logger.d("AuthenticationServiceHolder $authenticationServiceHolder")

        val originalRequest = chain.request()
        logger.d("Intercepting call to ${originalRequest.method()} ${originalRequest.url()}")

        val response: Response = chain.proceed(originalRequest)
        val successful = response.isSuccessful
        val code = response.code()
        logger.d("Response successful: $successful - code: $code")

        if (!successful && code == HttpURLConnection.HTTP_UNAUTHORIZED) {
            logger.d("Token is $token")

            val deviceUuid = deviceIdentificationManager.deviceUuid().blockingGet()
            logger.d("Device uuid $deviceUuid")
            if (deviceUuid != null) {
                val authenticationService = authenticationServiceHolder.get()
                if (authenticationService != null) {
                    token = reLogin(authenticationService, deviceUuid)
                    if (token != null) {
                        val headersBuilder = originalRequest.headers().newBuilder()
                        headersBuilder.removeAll(AUTHORIZATION_HEADER)
                        headersBuilder.add(AUTHORIZATION_HEADER, token!!)

                        val requestBuilder = originalRequest.newBuilder()
                        val request = requestBuilder.headers(headersBuilder.build()).build()
                        return chain.proceed(request)
                    } else {
                        logger.e("Token was not retrieved")
                    }
                } else {
                    logger.e("Authentication service is null!")
                }
            }
        }
        return response
}

reLogin() 方法是:

private fun reLogin(authenticationService: AuthenticationService, deviceUuid: UUID): String? {
        logger.d("reLogin() - authenticationService $authenticationService")
        val blockingGet = authenticationService?.login(LoginRequest(deviceUuid, clock.currentTime()))?.blockingGet()
        logger.d("reLogin() - response $blockingGet")
        val response = blockingGet ?: return null
        logger.d("reLogin() - token ${response.token}")
        return response.token
}

新: 正如Mitesh Machhoya 所说,我尝试了2 个不同的改造实例,一个有带有拦截器的okhttp 客户端,另一个没有。 现在登录调用没有被拦截但是拦截器的执行被破坏了,我的意思是这个类的日志跟踪是:

 - AuthenticationServiceHolder XXXmypackageXXX.AuthenticationServiceHolder... 
 - Intercepting call to GET XXXmyInterceptedCallXXX 
 - Response successful: false - code: 401 
 - Token is null 
 - Device uuid XXX 
 - reLogin() - authenticationService retrofit2.Retrofit$1@a5c0a25 

仅此而已。我的意思是reLogin() - response..... 没有打印出来。我确定登录调用正在工作,因为我在 okhttp 日志中看到了登录响应。

【问题讨论】:

  • okhttp Authenticator 更容易用于 401 处理和重试

标签: android kotlin retrofit retrofit2 okhttp


【解决方案1】:

在不附加拦截器的情况下与其他httpClient进行reLogin请求,然后它会像你预期的那样工作。

如果您使用相同的 httpClient 发出 reLogin 请求,那么它将通过拦截器并且每次都会覆盖请求,因此请尝试使用另一个 httpClient 发出请求

【讨论】:

  • 我刚刚试了一下,现在登录调用没有被拦截但是拦截器的执行被破坏了,我的意思是这个类的日志跟踪是: - AuthenticationServiceHolder XXXmypackageXXX.AuthenticationServiceHolder... -拦截对 GET XXXmyInterceptedCallXXX 的调用 - 响应成功:false - 代码:401 - 令牌为空 - 设备 uuid XXX - reLogin() - authenticationService retrofit2.Retrofit$1@a5c0a25 仅此而已。应该是reLogin() - response....。我确定登录调用正在工作,因为我看到了 okhttp 日志的响应
  • 不要进行阻塞调用,进行异步调用,看看发生了什么
  • AFAIK,拦截器内部的调用必须是同步的......如果不是,我如何将令牌添加到标头?
【解决方案2】:

粘贴的代码运行良好,登录请求正常,但登录响应在服务器端发生了变化,反序列化使其崩溃并破坏了链。

【讨论】:

    猜你喜欢
    • 2018-09-23
    • 2017-02-25
    • 2018-09-15
    • 1970-01-01
    • 2020-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多