首先,我为我糟糕的英语感到抱歉。我正在开发一个带有 nodejs 后端的 android 应用程序。JWT 用于授权,所以我将访问令牌发送到服务器以授权我的请求。访问令牌的寿命很短,在 60 秒后到期。为了刷新访问令牌,应用程序必须将刷新令牌发送到服务器。为此,我正在使用 OkHttp 身份验证器,但身份验证器不起作用。任何机构都可以帮我解决这个问题
服务生成器
public class ServiceGenerator {
private static final OkHttpClient httpClient =
new OkHttpClient.Builder()
.retryOnConnectionFailure(true)
.build();
private static final Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
public static Retrofit retrofit = builder.build();
public static <S> S createService(Class<S> serviceClass) {
Retrofit retrofit = builder.client(httpClient).build();
return retrofit.create(serviceClass);
}
public static <S> S createServiceWithAuth(Class<S> serviceClass, String accessToken, Context context) {
OkHttpClient newClient = httpClient.newBuilder().addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request.Builder builder = request.newBuilder();
if(!accessToken.isEmpty()){
builder.addHeader("x-auth-token", accessToken);
}
request = builder.build();
return chain.proceed((request));
}
}).authenticator(CustomAuthenticator.getInstance(accessToken, context))
.build();
Retrofit newRetrofit = retrofit.newBuilder().client(newClient).baseUrl(API_BASE_URL).addConverterFactory(GsonConverterFactory.create()).build();
return newRetrofit.create(serviceClass);
}
}
自定义身份验证器
public class CustomAuthenticator implements Authenticator {
private String accessToken;
private static CustomAuthenticator INSTANCE;
Context context;
private CustomAuthenticator(String accessToken, Context context){
this.accessToken = accessToken;
Hawk.init(context).build();
this.context = context;
}
static synchronized CustomAuthenticator getInstance(String accessToken, Context context){
if(INSTANCE == null){
INSTANCE = new CustomAuthenticator(accessToken, context);
}
return INSTANCE;
}
@Nullable
@Override
public Request authenticate(@Nullable Route route, @NotNull Response response) throws IOException {
if(responseCount(response) >= 2){
return null;
}
ApiClient client = ServiceGenerator.createService(ApiClient.class);
User user = new User();
user.setRefreshToken(Hawk.get("RefreshToken"));
Call<User> refreshAccessTokenCall = client.refresh(user);
retrofit2.Response<User> res = refreshAccessTokenCall.execute();
if(res.isSuccessful()){
assert res.body() != null;
String accessToken = res.body().getAccessToken();
Hawk.put("AccessToken", accessToken);
return response.request().newBuilder().addHeader("x-auth-token", res.body().getAccessToken()).build();
}else{
return null;
}
}
private int responseCount(Response response){
int result = 1;
while ((response = response.priorResponse()) != null){
result++;
}
return result;
}
}
以及将数据 POST 到服务器的方法(在 Fragment 中)
private void saveExpert() {
if (!validate()) {
return;
}
progressBar.setVisibility(View.VISIBLE);
Objects.requireNonNull(getActivity()).getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
String first_and_last_name = firstAndLastName.getText().toString();
String national_code = nationalCode.getText().toString();
String phone_number = phoneNumber.getText().toString();
String home_office_city = homeOfficeCity.getText().toString();
String _address = address.getText().toString();
String _field = field.getText().toString();
String sub_field = subField.getText().toString();
String _grade = grade.getText().toString();
ApiClient client = ServiceGenerator.createServiceWithAuth(ApiClient.class, Hawk.get("AccessToken"), getContext());
SetExpert setExpert = new SetExpert(first_and_last_name, national_code, phone_number, home_office_city, _address, _field, sub_field, _grade);
Call<Expert> expertCall = client.saveExpert(setExpert);
expertCall.enqueue(new Callback<Expert>() {
@Override
public void onResponse(@NotNull Call<Expert> call, @NotNull Response<Expert> response) {
if (response.isSuccessful()) {
Expert expert = response.body();
if (expert != null) {
Hawk.init(Objects.requireNonNull(getContext())).build();
Hawk.put("ExpertNationalCode", expert.getNational_code());
progressBar.setVisibility(View.GONE);
Objects.requireNonNull(getActivity()).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
new MaterialDialog.Builder(Objects.requireNonNull(getContext()))
.typeface("IRANSansWebMedium.ttf", "IRANSansWeb.ttf")
.title("پیام سیستم")
.content(expert.getFirst_and_last_name() + " عزیز با تشکر از ثبت نام شما. این ثبت نام به منزله تایید نهایی نبوده و پس از بررسی مشخصات و مدارک، با شما تماس گرفته خواهد شد.")
.positiveText("تایید.")
.canceledOnTouchOutside(false)
.onPositive(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
dismiss();
}
})
.show();
}
} else {
ApiError apiError = ErrorUtils.parseError(response);
progressBar.setVisibility(View.GONE);
Objects.requireNonNull(getActivity()).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
Toast.makeText(getContext(), apiError.getMessage(), Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(@NotNull Call<Expert> call, @NotNull Throwable t) {
progressBar.setVisibility(View.GONE);
Objects.requireNonNull(getActivity()).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
Toast.makeText(getContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}