1

我正在尝试将改造服务注入kodien。API 服务使用 Firebase Auth 令牌进行身份验证。因此,我必须通过从 Firebase Auth.getInstance().getIdToken() 获取令牌来将请求标头中的 id 令牌作为基本身份验证传递,该令牌在 Task 回调中提供令牌。现在我面临的问题是我必须将令牌传递给 http 客户端请求拦截器。我不知道该怎么做。

我已经查看了一些Kotlin Coroutines示例以寻求解决方案。但是我是 Kotlin Coroutines 的新手,并不能学到很多东西。

这是我的 kodien 对象。

override val kodein by Kodein.lazy {
    import(androidXModule(this@App))
    bind() from singleton { FirebaseDatabase.getInstance() }
    bind<ApiService>() from singleton {  RetrofitFactory.makeApiService() }
}

我的改装厂。

object RetrofitFactory {

    fun makeApiService(): ApiService {

        FirebaseAuth.getInstance().currentUser?.getIdToken(true)?.addOnCompleteListener {
            if (it.isSuccessful){
                // HERE IS THE TOKEN
                val token = it.result?.token
            }
        }

        val client = OkHttpClient.Builder()
                .addInterceptor {
                    val request = it.request().newBuilder()
                            .addHeader("authorization", "*** PASS TOKEN HERE ***")
                            .build()
                    it.proceed(request)
                }
                .build()

        return Retrofit.Builder()
                .client(client)
                .baseUrl(BuildConfig.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build()
                .create(ApiService::class.java)
    }

}

我可能完全错了,或者也许有更好的方法。

任何帮助表示赞赏。

提前致谢。

4

1 回答 1

1

我找到了解决方案。

TokenProvider在下面创建一个

class TokenProvider {

    private var token: String = ""

    fun get() = token

    fun load() {
        getToken {
            token = it
        }
    }

    private fun getToken(callback: (String) -> Unit) {
        FirebaseAuth.getInstance().currentUser?.getIdToken(true)?.addOnCompleteListener {
            if (it.isSuccessful){
                callback(it.result?.token!!)
            }
        }
    }
} 

注入TokenProviderin kodein

override val kodein by Kodein.lazy {
    import(androidXModule(this@App))
    bind() from singleton { TokenProvider() }
    bind<ApiService>() with singleton { RetrofitFactory.makeApiService(instance()) }
}

TokenProvider将tomakeServiceApi作为参数传递并使用它。

object RetrofitFactory {

    fun makeApiService(tokenProvider: TokenProvider): ApiService {

        val token = tokenProvider.get()

        val client = OkHttpClient.Builder()
                .addInterceptor {
                    val request = it.request()
                            .newBuilder()
                            .addHeader("authorization", "Bearer $token")
                            .build()
                    it.proceed(request)
                }
                .build()

        return Retrofit.Builder()
                .baseUrl(BuildConfig.BASE_URL)
                .client(client)
                .addConverterFactory(GsonConverterFactory.create())
                .build()
                .create(ApiService::class.java)
    }
}

最后,在 App 中加载令牌onCreate

override fun onCreate() {
    super.onCreate()
    val tokenProvider by instance<TokenProvider>()
    tokenProvider.load()
}

这个解决方案有一个极端情况。如果您在 App 加载后立即调用 Api。到那时,如果未加载 firebase 令牌。然后 Api 调用将失败。

这对我有用,因为我没有在 App 加载时调用 Api。仍在寻找可以解决这种极端情况的解决方案。一种解决方法是在调用 Api 之前等待令牌加载。

于 2020-03-07T17:39:58.063 回答