当前位置: 首页 > 知识库问答 >
问题:

如何在使用拦截器获取refreshtoken后调用相同的请求?

燕成双
2023-03-14

我正在创建使用改装的Android应用程序。我用Spring作为Restapi。我使用了JWT的身份验证。我在这里使用了两个拦截器。使用到期JWT调用BASE_URL/Helloapi的场景如下

>

  • 使用RequestInterceptor

    服务器检查令牌和响应代码401/403

    客户端检查响应代码并使用头中带有refreshtoken的ResponseInterceptor调用/刷新

    服务器检查refreshtoken并使用新accesstoken进行响应

    现在的问题是如何再次打电话/你好。每个请求我都要这个。我如何预测最后提出的请求。

    代码如下:

    调用/hello的代码的一部分

    btnNext.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
    
    
                    Call<HelloResponse> call= RetrofitFactoryWithJwt.getRetrofitInstance(getApplicationContext()).helloUser();
    
                    call.enqueue(new Callback<HelloResponse>() {
                        @Override
                        public void onResponse(Call<HelloResponse> call, Response<HelloResponse> response) {
                            Log.d(TAG,"after call in enque");
                            if(response.code()==200)
                            {
                                Log.d(TAG,response.body().getSuccess());
                            }
                            else
                            {
                                Log.d(TAG,"problem in response:"+response.code());
    
                            }
                        }
    
                        @Override
                        public void onFailure(Call<HelloResponse> call, Throwable t) {
                            Log.d(TAG,"onfailure"+t.getMessage());
                        }
                    });
    
                    Intent intent = new Intent( getApplicationContext(), MainActivity.class);
                    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
                    startActivity(intent);
                }
            });
    
    

    请求拦截器。JAVA

    public class RequestInterceptor implements Interceptor {
    
    
       Context context;
      String TAG="heyrequest";
    
        public RequestInterceptor(Context context)
        {
            this.context=context;
        }
        @Override
        public Response intercept(Chain chain) throws IOException {
    
            Request originalRequest = chain.request();
    
            //if url is /refresh add refresh token in header instead of accesstoken
            if(originalRequest.url().encodedPath().equalsIgnoreCase("/refresh"))
            {
    
                SharedPreferences preferences = context.getSharedPreferences("tokens", MODE_PRIVATE);
                String refreshvalue=preferences.getString("refreshtoken","");
    
    
                // rewrite the request
                Request newRequest=originalRequest.newBuilder()
                        .addHeader("Authorization","Bearer "+refreshvalue)
                        .build();
    
                return chain.proceed(newRequest);
            }
    
          //for context we have use requestinterceptor context construction
    
            SharedPreferences preferences = context.getSharedPreferences("tokens", MODE_PRIVATE);
            String tokenvalue=preferences.getString("accesstoken","");
    
            // rewrite the request
            Request newRequest=originalRequest.newBuilder()
                                .addHeader("Authorization","Bearer "+tokenvalue)
                                .build();
    
            return chain.proceed(newRequest);
        }
    }
    
    

    应答器。JAVA

    public class ResponseInterceptor implements Interceptor {
    
        Context context;
        String TAG="heyresponse";
        String accesstoken=null;
        Response response=null;
        public ResponseInterceptor(Context context)
        {
           this.context=context;
        }
    
        @Override
        public Response intercept(final Chain chain) throws IOException {
    
             final Request request=chain.request();
             response = chain.proceed(request);
            if(response.code()==401 || response.code()==403)
            {
               accesstoken=getNewToken();
            }
            return chain.proceed(request);
        }
    
        public String getNewToken()
        {
    
            Call<RefreshResponse> call= RetrofitFactoryWithJwt.getRetrofitInstance(context).refreshToken();
    
            call.enqueue(new Callback<RefreshResponse>() {
                @Override
                public void onResponse(Call<RefreshResponse> call, retrofit2.Response<RefreshResponse> response1) {
                    Log.d(TAG,"in refreshtoken call");
                    if(response1.code()==200)
                    {
    
                        accesstoken=response1.body().getAccesstoken();
                        Log.d(TAG,accesstoken);
    
                        SharedPreferences preferences = context.getSharedPreferences("tokens", MODE_PRIVATE);
                        preferences.edit().putString("accesstoken", accesstoken).apply();
    
                    }
                    else
                    {
                        Log.d(TAG,"problem in response:"+response1.code());
                    }
                }
    
                @Override
                public void onFailure(Call<RefreshResponse> call, Throwable t) {
                    Log.d(TAG,"onfailure:"+t.getMessage());
                }
            });
    
    return  accesstoken;
        }
    
    }
    
    
  • 共有1个答案

    盖博简
    2023-03-14

    我通过使用authenticator处理响应和拦截器在请求中添加头来解决这个问题

     类似资料:
    • 我在我的项目中使用。所有POST数据都以格式发送,并在服务器端解编入各自的bean中。类似于这样: 向服务器发送请求: 我从这里得到了REST拦截器的实现。 我想访问拦截器中的有效载荷(请求体)。由于数据是JSON格式的,因此不能作为请求参数访问。是否有一种方法可以在拦截器方法中获得请求正文?请指教。

    • 问题内容: 我在我的项目中使用。所有POST数据都以格式发送,并在服务器端解组到各自的bean中。像这样: 向服务器发送请求: 有效负载: 服务器端: MangaBean: 在控制台上输出: 我从这里获得了REST-interceptor实现。 我想访问拦截器中的有效负载(请求主体)。由于数据为JSON格式,因此无法将其作为请求参数进行访问。 有没有办法在拦截器方法中获取请求正文? 请指教。 问题

    • 问题内容: 我知道如何拦截所有请求,但是我只想拦截来自我资源的请求。 有谁知道如何做到这一点? 问题答案: 如果只想拦截来自特定资源的请求,则可以使用可选的action 属性。Angular的文档请参见此处(用法>操作) 的JavaScript Plunker:http ://plnkr.co/edit/xjJH1rdJyB6vvpDACJOT?p=preview

    • 问题内容: 我真的很感谢Spring 3阳极驱动的Web控制器映射 我有很多带有类似签名的控制器: 但是我的问题是,我想编写一个拦截器,该拦截器在处理后会通过BindingResults-如何从HttpRequest或HttpResponse中获取它们? 因为intercpetor方法具有相同的签名 问题答案: 因此,在@Axtavt的大力帮助下,我得出了结论,即可以在postHandle方法中从

    • 我正在尝试使用<code>网络客户端 谢谢 -斯里尼

    • Spring的处理器映射机制包含了处理器拦截器。拦截器在你需要为特定类型的请求应用一些功能时可能很有用,比如,检查用户身份等。 处理器映射处理过程配置的拦截器,必须实现 org.springframework.web.servlet包下的 HandlerInterceptor接口。这个接口定义了三个方法: preHandle(..),它在处理器实际执行 之前 会被执行; postHandle(..