【问题标题】:How to send updated Firebase Token with every Retrofit API call如何通过每次 Retrofit API 调用发送更新的 Firebase 令牌
【发布时间】:2021-04-14 19:23:34
【问题描述】:

每次我需要通过 Retrofit 在 Header 中发送我的 REST 请求时,我都想发送更新的令牌 (FirebaseAuth.getInstance().getAccessToken())。我已将 RetrofitClient 设置如下-

RetrofitClient.java

public class RetrofitClient {

    private static final String BASE_URL = "API_URL";
    private static RetrofitClient mInstance, mAuthInstance;
    private Retrofit retrofit;

    private RetrofitClient(boolean requireAuthorization, String firebaseID, Context context){

        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        //Put Custom Header i.e. 'InterceptorHeader' in all API request
        OkHttpClient okHttpClient;

        if(requireAuthorization)
            okHttpClient = new OkHttpClient.Builder()
                    .addInterceptor(new ConnectivityInterceptor(context))               // Header to check internet connectivity
                    .addInterceptor(new AuthorizationInterceptorHeader(firebaseID))     // Header Auth InterceptorHeader
                    .addInterceptor(loggingInterceptor).build();                        // Header for logging
        else
            okHttpClient = new OkHttpClient.Builder()
                    .addInterceptor(new ConnectivityInterceptor(context))    // Header to check internet connectivity
                    .addInterceptor(new InterceptorHeader())                 // Header InterceptorHeader
                    .addInterceptor(loggingInterceptor).build();             // Header for logging


        retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .client(okHttpClient) //adding custom OkHttp Client
                .build();
    }

    public static synchronized RetrofitClient getInstance(Context context){
        if(mInstance == null){
            mInstance = new RetrofitClient(false, null, context);
        }
        return mInstance;
    }

    public static synchronized RetrofitClient getAuthInstance(boolean requireAuthorization, String firebaseID, Context context){
        if(mAuthInstance == null){
            mAuthInstance = new RetrofitClient(requireAuthorization, firebaseID, context);
        }
        return mAuthInstance;
    }

    public TurnoAPI getTurnoApi(){
        return retrofit.create(TurnoAPI.class);
    }

}

AuthorizationInterceptorHeader.java

public class AuthorizationInterceptorHeader implements Interceptor {

    String firebaseID;

    public AuthorizationInterceptorHeader(String firebaseID) {
        this.firebaseID = firebaseID;
    }

    @NotNull
    @Override
    public Response intercept(@NotNull Chain chain) throws IOException {

        Request originalRequest = chain.request();

        //TODO change request header
        Request newRequest = originalRequest.newBuilder()
                .addHeader("Content-Type", "application/json")
                .addHeader("api-key", "api_key")
                .addHeader("api-hash", "api_key")
                .addHeader("**Authorization**", "FIREBASE_TOKEN")
                .build();
        return chain.proceed(newRequest);
    }
}

我想在标题中发送 FirebaseAuth.getInstance().getCurrentUser().getIdToken() 说 Authorization。现在因为 getIdToken() 正在返回一个任务,所以我不确定我需要如何设置以使用更新的 Firebase 令牌发出每个身份验证请求,任何解决方法都将不胜感激。谢谢。

【问题讨论】:

  • 也许this 可以帮助你。还有official docs
  • @OmGupta 是的,这是我们获取令牌的方式,但是如何在每个请求中发送更新的令牌......我不确定
  • 更新令牌是什么意思?
  • @OmGupta 更新令牌意味着我需要使用身份验证发送更新的令牌,因为如果我兑现它,令牌将在 1 小时内过期,我会更新它,我需要处理它并获取新令牌/或每次都不会过期的令牌
  • 我上面发送的链接已经回答了你的问题。每次调用 getIdToken() 方法时,将 forceRefresh 设为 true 都会为您获取更新的令牌,并且不会为您提供过期或无效的令牌。

标签: android firebase firebase-authentication retrofit2 access-token


【解决方案1】:

试试这个

FirebaseUserIdTokenInterceptor.java

public class FirebaseUserIdTokenInterceptor implements Interceptor {

    // Custom header for passing ID token in request.
    private static final String X_FIREBASE_ID_TOKEN = "YOUR-CUSTOM-HEADER";

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        try {
            FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
            if (user == null) return chain.proceed(request); // No has auth header

            Task<GetTokenResult> task = user.getIdToken(false);
            GetTokenResult tokenResult = Tasks.await(task, 10, TimeUnit.SECONDS); // Timeout 10 Seconds
            String idToken = tokenResult.getToken();
            if (idToken == null) return chain.proceed(request); // No has auth header

            return chain.proceed(request.newBuilder()
                    .addHeader(X_FIREBASE_ID_TOKEN, idToken)
                    .build()); // Has auth header
        } catch (Exception e) {
            return chain.proceed(request); // No has auth header
        }
    }
}

我找到了一个方法here 并为我修改了它。

【讨论】:

    【解决方案2】:

    这可能是我的错,因为我没有正确地提出我的问题。但我找到了解决方案并将其发布,以便对某人有所帮助。

    重构问题

    我试图将 FirebaseTokenID(JWT) 与我的每个 REST API 请求一起发送。我没有保留 tokenID 的本地副本,因为 tokenID 的生命周期很短,只有 1 小时。 要从 Firebase 获取 JWT,有以下方法-

    FirebaseAuth.getInstance().getCurrentUser().getIdToken()
    

    但这将返回一个任务,因此我必须管理对 getIDToken() 的调用,并等到返回任务完成后才能调用我的 API 方法。

    为了解决这个问题,我使用接口进行调用。

    TokenListener.java

    public interface TokenListener {
    
        void getToken(String firebaseToken);
    }
    

    FirebaseToken.java

    public class FirebaseToken {
    
        public static void getFirebaseToken(TokenListener tokenListener){
            FirebaseAuth.getInstance().getCurrentUser().getIdToken(false)
                    .addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
                        @Override
                        public void onComplete(@NonNull Task<GetTokenResult> task) {
                            if(task.isSuccessful())
                                tokenListener.getToken(task.getResult().getToken());
                        }
                    });
        }
    }
    

    现在从每个调用 API 并需要 TokenID 的类中,我正在实现 TokenListener 以获取当前/活动的 tokenID(JWT) 并继续调用我的 API 方法以将其用作参数标头通过 AuthorizationInterceptorHeader 添加到 RetrofitClient 类中。

    AuthorizationInterceptorHeader.java

    public class AuthorizationInterceptorHeader implements Interceptor {
    
        String firebaseToken;
    
        public AuthorizationInterceptorHeader(String firebaseToken) {
            this.firebaseToken = firebaseToken;
        }
    
        @NotNull
        @Override
        public Response intercept(@NotNull Chain chain) throws IOException {
    
            Request originalRequest = chain.request();
    
            Request newRequest = originalRequest.newBuilder()
                    .addHeader("Content-Type", "application/json")
                    .addHeader("api-key", "api-key")
                    .addHeader("api-hash", "api-hasg")
                    .addHeader("Authorization", firebaseToken)
                    .build();
            return chain.proceed(newRequest);
        }
    }
    

    编码愉快!!

    【讨论】:

      【解决方案3】:

      您可以从返回的任务中获取令牌,并将其发送到 header -

       task.getResult().getToken();
      

      【讨论】:

      • 如果我收到他们的任务,我将如何确定我是否在竞争任务之前发送令牌......?
      • 您需要将令牌值保存在首选项中并检查该值是否存在。如果存在值,则可以添加到标题中,如果不存在,则可以调用将首先提供值的函数。
      猜你喜欢
      • 2020-01-26
      • 2021-08-29
      • 2016-04-07
      • 1970-01-01
      • 2018-04-07
      • 2021-10-16
      • 2017-10-02
      • 2019-07-04
      • 2016-10-06
      相关资源
      最近更新 更多