0

我想在 HttpAuthenticationInterceptor 的身份验证方法中添加刷新令牌调用,以管理 401 未授权响应的 access_token 到期。

我使用改造 2 的 serviceClient 接口(serviceGateway)在身份验证方法中添加了 refresh_token 的同步调用。但是在拦截器中注入 serviceGateway 时我面临循环依赖问题。我是否需要为此刷新令牌调用创建一个单独的 ServiceClient 接口?

这是我的 AuthenticationInterceptor 和 NetworkModule 类

class AuthenticationInterceptor @Inject constructor(private val preferences: SharedPreferencesKeyValueDataSource, private val serviceGateway: ServiceGateway) : Interceptor, Authenticator{

    @Throws(IOException::class)
    override fun authenticate(route: Route?, response: Response): Request?{
        if (response.code() == 401) {
            val credentials = Credentials.basic("dummy", "dummy")
            val refreshCall = serviceGateway.refreshToken(credentials, preferences.getValue(Constants.REFRESH_TOKEN, ""))

            //make it as retrofit synchronous call
            val refreshResponse = refreshCall.execute()
            return if (refreshResponse.code() == 200) {
                //Save the access token and refresh token in preferences
                refreshResponse.body()?.let{
                    preferences.setValue(Constants.ACCESS_TOKEN, it.access_token)
                    preferences.setValue(Constants.REFRESH_TOKEN, it.refresh_token)
                }
                val newAccessToken = refreshResponse.body()?.access_token
                response.request().newBuilder()
                        .header(AuthenticationInterceptor.AUTHORIZATION, "Bearer $newAccessToken")
                        .build()
            } else {
                null
            }
        }
        return null
    }
}

//下面是来自NetworkModule的代码,

@Provides
    @Singleton
    fun provideAuthenticationInterceptor(preferences: SharedPreferencesKeyValueDataSource, serviceGateway: ServiceGateway) = AuthenticationInterceptor(preferences, serviceGateway)

    @Provides
    @Singleton
    fun provideOkhttpClient(loggingInterceptor: HttpLoggingInterceptor,
                            authenticationInterceptor: AuthenticationInterceptor): OkHttpClient {

        val client = OkHttpClient.Builder()
        client.addInterceptor(loggingInterceptor)
        client.addInterceptor(authenticationInterceptor)
        client.authenticator(authenticationInterceptor)
        client.connectTimeout(15, TimeUnit.SECONDS)
        client.readTimeout(20, TimeUnit.SECONDS)
        return client.build()
    }


    @Provides
    @Singleton
    fun provideRetrofit(gson: Gson, okHttpClient: OkHttpClient,
                        @Named("BASE_URL_CORE") baseUrl: String)
            : Retrofit {

        return Retrofit.Builder()
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create(gson))
                .baseUrl(baseUrl)
                .client(okHttpClient)
                .build()
    }

    @Provides
    @Singleton
    fun provideGateway(retrofit: Retrofit): ServiceGateway {
        return retrofit.create(ServiceGateway::class.java)
    }

编译器错误是...

  • ServiceGateway 在 ...NetworkModule.provideAuthenticationInterceptor(..., serviceGateway) 注入

  • AuthenticationInterceptor 在...NetworkModule.provideOkhttpClient(..., authenticationInterceptor)处注入
  • okhttp3.OkHttpClient 在 ...NetworkModule.provideRetrofit(..., okHttpClient, ...) 处注入
  • retrofit2.Retrofit 在 ...NetworkModule.provideGateway(retrofit) 处注入
4

1 回答 1

0

我为 ServiceGateway 尝试了 Dagger Lazy Injection(import daggger.Lazy),它在没有 Dagger 循环依赖的情况下工作正常。

class AuthenticationInterceptor @Inject constructor(private val preferences: SharedPreferencesKeyValueDataSource, private val serviceGateway: Lazy<ServiceGateway>) : Interceptor, Authenticator{
}

RefreshToken api 现在正在调用,但这会导致另一个问题(循环刷新令牌调用)。因此,要解决此循环刷新令牌调用问题,最好为刷新令牌调用创建一个单独的 serviceGateway,就像Yasin Kaçmaz在这里回答的这些家伙一样。另一种解决方案是直接在 Okhttp 上调用 refresh-token(不使用 Retrofit 服务接口)

感谢Aamir Abro帮助我解决了这个问题。

于 2019-07-07T07:15:40.587 回答