无法使用 Retrofit 刷新 Bearer Token
Unable to Refresh Bearer Token using Retrofit
我在我的项目中使用 Retrofit 和 OkHttp,我想在服务器给出 401 错误代码时刷新令牌并将新令牌存储在共享首选项中,然后在不通知用户的情况下再次进行相同的调用。令牌类型为不记名,每小时过期。
但是我想要的输出没有出现,当令牌过期时,身份验证器什么都不做。
ApiInterface.java
public interface ApiInterface {
@FormUrlEncoded
@POST("auth/login")
Call<ResponseBody> login(@FieldMap HashMap<String, Object> map);
@FormUrlEncoded
@POST("auth/register")
Call<ResponseBody> register(@FieldMap HashMap<String, Object> map);
@FormUrlEncoded
@POST("auth/forgotpassword")
Call<ResponseBody> forgotPassword(@FieldMap HashMap<String, Object> map);
@POST("auth/refresh")
Call<ResponseBody> refreshToken(@Header("Authorization") String token);
@POST("auth/GetAllInterests")
Call<ResponseBody> getAllInterest();
@POST("auth/AddUserProfile")
@Multipart
Call<ResponseBody> addUserProfile(
@Part("display_name") RequestBody display_name,
@Part("children_age_show") RequestBody children_age_show,
@Part("address") RequestBody address,
@Part("no_of_children") RequestBody no_of_children,
@Part("children_age") RequestBody children_age,
@Part("date_of_birth") RequestBody date_of_birth,
@Part("interests") RequestBody interests,
@Part List<MultipartBody.Part> images
);
@POST("auth/GetUserProfile")
Call<ResponseBody> getUserProfile();
@FormUrlEncoded
@POST("auth/ChangePassword")
Call<ResponseBody> changePassword(@FieldMap HashMap<String, Object> map);
@POST("auth/logout")
Call<ResponseBody> logout();
}
ApiClient.java
public class ApiClient {
private static Retrofit retrofit = null;
private static ApiInterface apiInterface = null;
public static Retrofit getRetrofit(Context context) {
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (AppPreference.getPreference(context, AppPersistence.keys.AUTH_TOKEN) != null) {
request = request.newBuilder()
.addHeader("Authorization", AppPreference.getPreference(context, AppPersistence.keys.AUTH_TOKEN))
.build();
}
return chain.proceed(request);
}
})
.authenticator(new TokenAuthenticator(context))
.build();
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
}
return retrofit;
}
public static ApiInterface getApiInterface(Context context) {
if (apiInterface == null) {
getRetrofit(context);
apiInterface = retrofit.create(ApiInterface.class);
}
return apiInterface;
}
}
TokenAuthenticator.java
public class TokenAuthenticator implements Authenticator {
Context context;
public TokenAuthenticator(Context context) {
this.context = context;
}
@Override
public Request authenticate(Route route, Response response) throws IOException {
Log.d("Authenticator", "Authenticator Called");
if (response.code() == 401) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
Log.d("Authenticator", "Requesting for New Token");
ApiInterface apiInterface = retrofit.create(ApiInterface.class);
retrofit2.Response<ResponseBody> response1 = apiInterface
.refreshToken(AppPreference.getPreference(context, AppPersistence.keys.AUTH_TOKEN))
.execute();
if (response1.isSuccessful()) {
try {
String body = response1.body().string();
JSONObject jsonObject = new JSONObject(body);
if (jsonObject.getBoolean("status")) {
String newToken = "Bearer " + jsonObject.getJSONObject("Data").getString("access_token");
AppPreference.setPreference(context, AppPersistence.keys.AUTH_TOKEN, newToken);
Log.d("Authenticator", "New Token Generated");
return response.request().newBuilder()
.header("Authorization", newToken)
.build();
}
} catch (Exception e) {
Log.e("TokenAuthenticator", e.getMessage(), e);
}
}
Toast.makeText(context, response1.body().string(), Toast.LENGTH_SHORT).show();
}
return null;
}
}
请尝试以下方式
(1) HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
try {
httpClient.addInterceptor(new Interceptor() {
@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
// try the request
Response response = chain.proceed(request);
if (response shows expired token) {
// get a new token (I use a synchronous Retrofit call)
// create a new request and modify it accordingly using the new token
Request newRequest = request.newBuilder().build();
// retry the request
return chain.proceed(newRequest);
}
// otherwise just pass the original response on
return response;
}
});
} catch (Exception e) {
e.printStackTrace();
}
String baseUrl = "";
Retrofit retrofit = new Retrofit.Builder()
.client(okHttpClient)
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
apiService = retrofit.create(ApiService.class);
(2) public class TokenAuthenticator implements Authenticator {
private final ApiService apiservice;
public TokenAuthenticator(TokenServiceHolder tokenServiceHolder) {
this.tokenServiceHolder = tokenServiceHolder;
}
@Override
public Request authenticate(Proxy proxy, Response response) throws IOException {
newtoken = apiservice.refreshToken().execute();
return response.request().newBuilder()
.header(AUTHORIZATIONKEY, newtoken)
.build();
}
@Override
public Request authenticateProxy(Proxy proxy, Response response) throws IOException {
// Null indicates no attempt to authenticate.
return null;
}
}
希望对您有所帮助
我在我的项目中使用 Retrofit 和 OkHttp,我想在服务器给出 401 错误代码时刷新令牌并将新令牌存储在共享首选项中,然后在不通知用户的情况下再次进行相同的调用。令牌类型为不记名,每小时过期。
但是我想要的输出没有出现,当令牌过期时,身份验证器什么都不做。
ApiInterface.java
public interface ApiInterface {
@FormUrlEncoded
@POST("auth/login")
Call<ResponseBody> login(@FieldMap HashMap<String, Object> map);
@FormUrlEncoded
@POST("auth/register")
Call<ResponseBody> register(@FieldMap HashMap<String, Object> map);
@FormUrlEncoded
@POST("auth/forgotpassword")
Call<ResponseBody> forgotPassword(@FieldMap HashMap<String, Object> map);
@POST("auth/refresh")
Call<ResponseBody> refreshToken(@Header("Authorization") String token);
@POST("auth/GetAllInterests")
Call<ResponseBody> getAllInterest();
@POST("auth/AddUserProfile")
@Multipart
Call<ResponseBody> addUserProfile(
@Part("display_name") RequestBody display_name,
@Part("children_age_show") RequestBody children_age_show,
@Part("address") RequestBody address,
@Part("no_of_children") RequestBody no_of_children,
@Part("children_age") RequestBody children_age,
@Part("date_of_birth") RequestBody date_of_birth,
@Part("interests") RequestBody interests,
@Part List<MultipartBody.Part> images
);
@POST("auth/GetUserProfile")
Call<ResponseBody> getUserProfile();
@FormUrlEncoded
@POST("auth/ChangePassword")
Call<ResponseBody> changePassword(@FieldMap HashMap<String, Object> map);
@POST("auth/logout")
Call<ResponseBody> logout();
}
ApiClient.java
public class ApiClient {
private static Retrofit retrofit = null;
private static ApiInterface apiInterface = null;
public static Retrofit getRetrofit(Context context) {
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (AppPreference.getPreference(context, AppPersistence.keys.AUTH_TOKEN) != null) {
request = request.newBuilder()
.addHeader("Authorization", AppPreference.getPreference(context, AppPersistence.keys.AUTH_TOKEN))
.build();
}
return chain.proceed(request);
}
})
.authenticator(new TokenAuthenticator(context))
.build();
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
}
return retrofit;
}
public static ApiInterface getApiInterface(Context context) {
if (apiInterface == null) {
getRetrofit(context);
apiInterface = retrofit.create(ApiInterface.class);
}
return apiInterface;
}
}
TokenAuthenticator.java
public class TokenAuthenticator implements Authenticator {
Context context;
public TokenAuthenticator(Context context) {
this.context = context;
}
@Override
public Request authenticate(Route route, Response response) throws IOException {
Log.d("Authenticator", "Authenticator Called");
if (response.code() == 401) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
Log.d("Authenticator", "Requesting for New Token");
ApiInterface apiInterface = retrofit.create(ApiInterface.class);
retrofit2.Response<ResponseBody> response1 = apiInterface
.refreshToken(AppPreference.getPreference(context, AppPersistence.keys.AUTH_TOKEN))
.execute();
if (response1.isSuccessful()) {
try {
String body = response1.body().string();
JSONObject jsonObject = new JSONObject(body);
if (jsonObject.getBoolean("status")) {
String newToken = "Bearer " + jsonObject.getJSONObject("Data").getString("access_token");
AppPreference.setPreference(context, AppPersistence.keys.AUTH_TOKEN, newToken);
Log.d("Authenticator", "New Token Generated");
return response.request().newBuilder()
.header("Authorization", newToken)
.build();
}
} catch (Exception e) {
Log.e("TokenAuthenticator", e.getMessage(), e);
}
}
Toast.makeText(context, response1.body().string(), Toast.LENGTH_SHORT).show();
}
return null;
}
}
请尝试以下方式
(1) HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
try {
httpClient.addInterceptor(new Interceptor() {
@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
// try the request
Response response = chain.proceed(request);
if (response shows expired token) {
// get a new token (I use a synchronous Retrofit call)
// create a new request and modify it accordingly using the new token
Request newRequest = request.newBuilder().build();
// retry the request
return chain.proceed(newRequest);
}
// otherwise just pass the original response on
return response;
}
});
} catch (Exception e) {
e.printStackTrace();
}
String baseUrl = "";
Retrofit retrofit = new Retrofit.Builder()
.client(okHttpClient)
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
apiService = retrofit.create(ApiService.class);
(2) public class TokenAuthenticator implements Authenticator {
private final ApiService apiservice;
public TokenAuthenticator(TokenServiceHolder tokenServiceHolder) {
this.tokenServiceHolder = tokenServiceHolder;
}
@Override
public Request authenticate(Proxy proxy, Response response) throws IOException {
newtoken = apiservice.refreshToken().execute();
return response.request().newBuilder()
.header(AUTHORIZATIONKEY, newtoken)
.build();
}
@Override
public Request authenticateProxy(Proxy proxy, Response response) throws IOException {
// Null indicates no attempt to authenticate.
return null;
}
}
希望对您有所帮助