Retrofit2拦截器,仅在特定方法中使用令牌

时间:2019-03-20 10:39:32

标签: android authorization retrofit2 interceptor okhttp3

我想在authorization中使用Retrofit2。我选择interceptor的方式是因为几乎所有方法都需要authorization,除了我要获取令牌以供其他方法进一步使用的一种方法。

我的问题是:我该如何实现?

我将访问令牌存储在SharedPreferences中。我的第一个想法是:“ 我可以在我的RetrofitClient类中检索它,并根据令牌是否为null或是否具有值来创建合适的Retrofit实例”(添加或不添加{ {1}}。

不幸的是,这并不容易,因为需要.client()才能获得偏好。

我不知道如何将其传递给Context类或如何将其传递给内部。

这是我的RetrofitClient班:

RetrofitClient

我的public class RetrofitClient { public static final String BASE_URL = "http://localhost"; public static Retrofit retrofit = null; private RetrofitClient() { retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) //.client(getRequestHeader()) .build(); } /*OkHttpClient client = new OkHttpClient.Builder().addInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request newRequest = chain.request().newBuilder() .addHeader("Authorization", "Bearer" + ) } })*/ public static synchronized Retrofit getInstance() { if (retrofit == null) { retrofit = new Retrofit.Builder().baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()).build(); } return retrofit; } public Api getApi() { return retrofit.create(Api.class); } } 是我设置超时的先前方法。

我想创建这样的实例:

getRequestHeader()

然后:
private RetrofitClient() { tokenService.token = null; tokenService.readToken(ApplicationContext.getInstance()); if (tokenService.token == null) { retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); } else { retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .client(client) //I have interceptor here with access token .build(); } } //获取令牌
RetrofitClient.getInstance().create(Api.class).getToken() //当我获得令牌时

这是好方法吗?

3 个答案:

答案 0 :(得分:1)

您可以使用应用程序处于活动状态时可用的应用程序上下文。从您的应用程序类中获取它:

public class MyApp extends Application {
    private static MyApp instance;
    @Override
    public void onCreate() {
    super.onCreate();
    instance = this;
    //other code
}
public static MyApp getInstance() {
    return instance;
}

然后只需使用MyApp.getInstance()即可在需要的地方获取上下文。使用这种方法,您可以实现之前的想法,并在RetrofitClient类中获得SharedPreferences。

别忘了添加您的应用程序类以进行显示。

更新: 您只创建一次改造实例,因此,如果您在拥有令牌时创建它-您将始终在应用程序运行时使用它。 我认为,好的做法是在拦截器中检查令牌。像这样:

new Interceptor() {
        @Override
        public Response intercept(@NonNull Chain chain) throws IOException {
            Request request = chain.request();
            if (tokenService.token == null) {
                return chain.proceed(request);
            } else {
                return chain.proceed(request.newBuilder().addHeader("Authorization", "Bearer" + tokenService.token).build());
            }
        }
    }

此外,我不知道您的tokenService的工作方式。但是请记住,最好的办法是始终签入令牌的共享首选项,如果您在注销时在此清除令牌。因为即使在共享首选项中将其清除,您的tokenService仍可能保留令牌字符串。

答案 1 :(得分:0)

只需根据情况将SharedPreferences添加为RetrofitClient或其他中的构造函数参数

答案 2 :(得分:0)

您可以通过以下方式进行操作:

首先使用单例实例创建一个首选项类

  

首选项

public class Preferences {

    public static Preferences INSTANCE;
    private final String PREFERENCE_FILE = "my_preferences";
    public final String PREF_TOKEN = "pref_user_token";
    private SharedPreferences mPrefs;
    private SharedPreferences.Editor mEdit;

    private Preferences() {
        Application app = MyApplicationClass.getInstance();
        mPrefs = app.getSharedPreferences(PREFERENCE_FILE, Context.MODE_PRIVATE);
        mEdit = mPrefs.edit();
    }

    // Returns singleton instance
    public static Preferences getInstance() {
        if (INSTANCE == null)
            INSTANCE = new Preferences();
        return INSTANCE;
    }

    public String getToken() {
        return Preferences.getInstance().mPrefs.getString(PREF_TOKEN, "");
    }

    public void saveToken(String value) {
        mEdit.putString(PREF_TOKEN, value);
        mEdit.apply();
    }

}

然后在RetrofitClient类中进行如下更改:

  

RetrofitClient

public class RetrofitClient {

    public static final String BASE_URL = "http://localhost";
    public static Retrofit retrofit = null;

    private RetrofitClient() {
        retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .client(mClient)
                .build();
    }

    OkHttpClient mClient = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request newRequest = chain.request().newBuilder()
                    .addHeader("Authorization", "Bearer" + Preferences.getInstance().getToken())
        }
    })

    public static synchronized Retrofit getInstance() {
        if (retrofit == null) {

            retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create()).build();
        }
        return retrofit;
    }

    public Api getApi() {
        return retrofit.create(Api.class);
    }
}