【问题标题】:How to inject retrofit service with Firebase ID Token into kodein如何将带有 Firebase ID 令牌的改造服务注入 kodein
【发布时间】:2020-06-18 04:46:47
【问题描述】:

我正在尝试将retrofit 服务注入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)
    }

}

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

感谢任何帮助。

提前致谢。

【问题讨论】:

    标签: android firebase retrofit2 kotlin-coroutines kodein


    【解决方案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!!)
                }
            }
        }
    } 
    

    在kodein中注入TokenProvider

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

    TokenProvider 传递给makeServiceApi 作为参数并使用它。

    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调用就会失败。

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

    【讨论】:

    • 您好 Varun,您找到完整的解决方案了吗?
    • 不错,但是token过期的情况呢?你有什么想法吗?
    猜你喜欢
    • 1970-01-01
    • 2017-05-21
    • 2019-05-06
    • 2020-04-20
    • 2016-02-08
    • 2016-11-29
    • 1970-01-01
    • 2019-04-09
    • 1970-01-01
    相关资源
    最近更新 更多