1

首先,我为我糟糕的英语感到抱歉。我正在开发一个带有 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();
            }
        });
    }
4

1 回答 1

0

removeHeader("x-auth-token")可以解决这个问题。

return response.request().newBuilder()
    .removeHeader("x-auth-token") // Remove old header
    .addHeader("x-auth-token", res.body().getAccessToken())
    .build();

removeHeader()似乎需要防止发送旧的“x-auth-token” 。

于 2022-01-17T01:55:57.363 回答