IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android接口请求处理Token过期以及并发处理解决方案 -> 正文阅读

[移动开发]Android接口请求处理Token过期以及并发处理解决方案

服务端API请求现在基本上都会设置token,用来保证接口识别安全和验证,一般来说token都会设置一个有效的时间,当时间过期之后我们需要重新获取一个新的token,从而保证接口的安全性。
那么,当token有效时间过期后我们应该怎样处理了,有两种方案,分别是手动处理和自动处理,选择哪种方案就看看应用适合哪种场景。

手动处理

手动处理意味着当token过期后需要客户手动点击重新获取一个新的token,常规做法是当token过期后,应用直接跳转至登录界面,重新走一遍登录的流程,获取新的token,更新本地缓存,从而保证后续接口的正常请求操作。

首先,怎么判断接口token失效,我的接口请求是采用Retrofit+Okhttp框架,需要在Retrofit请求中配置拦截,如图代码示例

 retrofit = new Retrofit.Builder().client(new OkHttpClient.Builder()
                .addInterceptor(new Interceptor() {
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        Request newRequest = chain.request().newBuilder()
                                .addHeader("Authorization", UserHelpers.getInstance().getAuthorization())
                                .build();
                        Response proceed = chain.proceed(newRequest);
                        /*token过期重新登录*/
                        if(isTokenExpired(proceed))
                        loginAgain();
                        else
                            isTokenExpire=false;
                        return proceed;
                    }
                })
                .addInterceptor(interceptor)
                .retryOnConnectionFailure(true)
                .readTimeout(TIMEOUT_READ, TimeUnit.SECONDS)
                .connectTimeout(TIMEOUT_CONNECTION, TimeUnit.SECONDS)
                .build()).baseUrl(RetrofitWrapper.Constant.BASE_URL).addConverterFactory(
                GsonConverterFactory.create()).addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build();

在新增的 addInterceptor中配置回调结果的拦截,如果出现token异常则走对应的流程进行重新登录。

isTokenExpired根据回调接口判断token是否过期

private boolean isTokenExpired(Response response) {
        try {
            ResponseBody responseBody = response.body();
            BufferedSource source = responseBody.source();
            source.request(Long.MAX_VALUE); // Buffer the entire body.
            Buffer buffer = source.getBuffer();
            Charset UTF8 = Charset.forName("UTF-8");
            String string = buffer.clone().readString(UTF8);
            ResponseEntity responseEntity = ResponseWrapper.getResponseEntity(string);
            if(responseEntity.getCode()==MSG_CODE_TOKEN_FAIL)
                return true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

loginAgain()重新跳转登录界面

 private void loginAgain()
   {
           Activity activity = ScreenManager.getScreenManager().currentActivity();
           if (activity != null) {
               activity.startActivity(new Intent(activity, LoginActivity.class)
                       .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK));
               ScreenManager.getScreenManager().popAllActivity();
           }
   } 

这里有很多种实现的方法,目的就是正常跳转登录界面即可

自动处理

自动处理的方案原理就是当token判断失效后,马上获取一个新的token保证接口能正常请求完成

  retrofit = new Retrofit.Builder().client(new OkHttpClient.Builder()
                .addInterceptor(new Interceptor() {
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        Request newRequest = chain.request().newBuilder()
                                .addHeader("Authorization", UserHelpers.getInstance().getAuthorization())
                                .build();
                        Response proceed = chain.proceed(newRequest);
//                        /*token过期重新登录*/
//                        if(isTokenExpired(proceed))
//                        loginAgain();
//                        else
//                            isTokenExpire=false;
                        if(isTokenExpired(proceed)) {
                            String newToken = getNewToken();
                            //使用新的Token,创建新的请求
                            Request newAgainRequest = chain.request().newBuilder()
                                    .addHeader("Authorization", newToken)
                                    .build();
                            return chain.proceed(newAgainRequest);
                        }
                        return proceed;
                    }
                })
                .addInterceptor(interceptor)
                .retryOnConnectionFailure(true)
                .readTimeout(TIMEOUT_READ, TimeUnit.SECONDS)
                .connectTimeout(TIMEOUT_CONNECTION, TimeUnit.SECONDS)
                .build()).baseUrl(RetrofitWrapper.Constant.BASE_URL).addConverterFactory(
                GsonConverterFactory.create()).addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build();

如图当token过期后,我们马上获取一个新的token从而继续完成整个接口请求。

getNewToken()获取一个新的token

private String getNewToken() throws IOException {
        Retrofit retrofit= new Retrofit.Builder()
                /*API的主机地址*/
                .baseUrl("https://url")
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        retrofit2.Response<JsonObject> requestToken = retrofit.create(ApiProtocol.class).DriverLogin().execute();
        /*生成新的token*/
        String token=requestToken.body().get("Token").toString();
        /*需要更新本地的token保存*/
        return token;
    }

并发处理

很多时候我们可能存在多个接口并发请求的情况,这个时候如果token失效,我们需要做一些特殊的处理,如果手动解决方案,我们参考下面的解决方案
在跳转的时候加一个token过期标识判断,当第一个接口已经判断token过期后,后续的的无需在处理
/token过期重新登录/

  if(isTokenExpired(proceed))
   loginAgain();
  else
   isTokenExpire=false;
   
 private void loginAgain()
   {
       /*处理并发请求过期判断*/
          if(isTokenExpire)
           return;
          else
           isTokenExpire=true;
           Activity activity = ScreenManager.getScreenManager().currentActivity();
           if (activity != null) {
               activity.startActivity(new Intent(activity, LoginActivity.class)
                       .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK));
               ScreenManager.getScreenManager().popAllActivity();
           }
   }

如果是自动解决方案则在处理刷新的token的方法中需要采用同步的方式,这样第一个接口处理刷新完token后,后续的接口都可以正常请求接口。

@Synchronized
    private String getNewToken() throws IOException {
        Retrofit retrofit= new Retrofit.Builder()
                /*API的主机地址*/
                .baseUrl("https://url")
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        retrofit2.Response<JsonObject> requestToken = retrofit.create(ApiProtocol.class).DriverLogin().execute();
        /*生成新的token*/
        String token=requestToken.body().get("Token").toString();
        /*需要更新本地的token保存*/
        return token;
    }

关于token过期的处理方案的分享就到这里,如果你还有更好的方案,欢迎留言分享

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-08-06 10:55:38  更:2022-08-06 10:57:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 4:28:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码