【问题标题】:Update request header when access token updates Dagger and Retrofit访问令牌更新 Dagger 和 Retrofit 时更新请求标头
【发布时间】:2016-08-25 03:07:13
【问题描述】:

我想在网络请求中更新访问令牌。但是使用 Dagger 和 Retrofit 有一些困难。

????对不起,我的英文不好,所以给你一个例子可能会很清楚。从头开始,我的想法是这样的:

提供保存在共享首选项中的访问令牌

@Provides
@ForOauth
Preference<String> provideAccessToken(RxSharedPreferences prefs) {
    return prefs.getString(PrefsUtils.KEY_ACCESS_TOKEN);
}

使用访问令牌创建拦截器并添加到okhttp客户端

@Provides
@Singleton
@Named("Cached")
public OkHttpClient provideOkHttpClientWithCache(Application application, @ForOauth OauthInterceptor oauthInterceptor) {
      ...
    builder.addInterceptor(oauthInterceptor);
      ...
}

我通过其构造函数提供OauthInterceptor 实例

@Inject
public OauthInterceptor(@ForOauth Preference<String> accessToken) {
    this.accessToken = accessToken;
    Timber.tag("OauthInterceptor");
}

但是由于 okhttp 客户端是单例的,当 prefs 中的访问令牌更新时它不会改变。我认为可能可行的另一种方法是使用自定义范围,如 @ForOauth 或其他东西,但这只是一个粗略的草图...

顺便说一句,我还有一个这样的想法:

intercept() 方法中从首选项获取访问令牌,因此每次我都可以获得一个包含最新访问令牌的请求标头。

@Override
public Response intercept(Chain chain) throws IOException {
    Request.Builder builder = chain.request().newBuilder();
    if (accessToken.isSet()) {
        // Preference<String> accessToken
        builder.header("Authorization", ACCESS_TYPE + accessToken.get());
    } else {
        builder.header("Authorization", "Bearer xxxxxx");
    }
    return chain.proceed(builder.build());
}

但是我还没有真正尝试过这个想法,而且我认为它不对????

我想知道我是否必须每次都创建一个新的 okhttp 客户端实例,或者我可以只更新访问令牌然后 okhttp 客户端单例可以刷新它的拦截器...

所以你能给我一些建议,或者一个简单的工作示例。

提前谢谢????

【问题讨论】:

    标签: android retrofit dagger okhttp3


    【解决方案1】:

    嗯,我已经这样做了很多次,但从未注意到访问令牌刷新没有沿着链向下传递到 OkHttp 的任何问题。这是我在应用程序中使用的典型设置:

    @Provides @Singleton
    SharedPreferences providePreferences(Context ctx) {
        return new SharedPreferences(ctx);
    }
    
    @Provides @Singleton
    HttpLoggingInterceptor provideLoggingInterceptor(){
        return new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY);
    }
    
    @Provides @Singleton
    OkHttpClient provideClient(HttpLoggingInterceptor interceptor, SharedPreferences prefs){
        return new OkHttpClient.Builder()
                .addNetworkInterceptor(chain -> {
                    // Add Auth Header
                    String token = prefs.accessToken().get();
                    if(token == null) token = "";
    
                    Request request = chain.request().newBuilder().addHeader("Authorization", token).build();
                    return chain.proceed(request);
                })
                .addInterceptor(interceptor)
                .build();
    }
    
    @Provides @Singleton
    Retrofit provideRetrofit(@ApiUrl String url, OkHttpClient client){
        return new Retrofit.Builder()
                .baseUrl(url)
                .client(client)
                .addConverterFactory(LoganSquareConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
    }
    

    SharedPreferences 只是我将一些RxSharedPreferences 逻辑抽象到的类。也可以@Inject 在应用程序中任何需要它的地方使用它,这很好。这是该类的一个简单版本,只是为了好玩:

    public class SharedPreferences {
        // Constants and variables
        private static final String PREFERENCE_FILENAME = BuildConfig.APPLICATION_ID + ".prefs";
        private static final String PREF_ACCESS_TOKEN= "pref_access_token";
    
        private RxSharedPreferences mRxSharedPrefs;
    
        // Constructor
        public SharedPreferences(Context context) {
            mRxSharedPrefs = RxSharedPreferences.create(context.getSharedPreferences(PREFERENCE_FILENAME, Context.MODE_PRIVATE));
        }
    
        // Helper methods
        public Preference<String> accessToken() { return mRxSharedPrefs.getString(PREF_ACCESS_TOKEN, ""); }
    
        public void logout() { accessToken().delete(); }
    }
    

    【讨论】:

    • 这真的有用吗?如果我在我的活动中注入改造,比如说,并发出一个返回我存储到共享首选项中的 authtoken 的请求。这是否意味着我将能够使用相同的改造实例发出经过身份验证的请求?我认为不会。需要有一种方法来重新注入或更新改造。
    • 每次发出 HTTP 请求时读取首选项似乎不是最好的主意。
    猜你喜欢
    • 2018-09-20
    • 1970-01-01
    • 1970-01-01
    • 2017-11-07
    • 2018-09-23
    • 1970-01-01
    • 2022-12-23
    • 2018-09-02
    • 2021-02-01
    相关资源
    最近更新 更多