查看: 2031|回复: 0

[Android教程] OkHttp实现全局过期token自动刷新

发表于 2018-3-1 08:02:15
#遇到问题:

当前开发的 App 遇到一个问题:

当请求某个接口时,由于 token 已经失效,所以接口会报错。
但是产品经理希望 app 能够马上刷新 token ,然后重复请求刚才那个接口,这个过程对用户来说是无感的。
>
也就是静默自动登录,然后继续请求:
>
请求 A 接口-》服务器返回 token 过期-》请求 token 刷新接口-》请求 A 接口
>
要实现上述需求的话,大家会如何实现呢?

#解决方案:

思路:
1.通过拦截器,获取返回的数据
2.判断token是否过期
3.如果token过期则刷新token
4.使用最新的token,重新请求网络数据

  1. 1 /**
  2. 2 * 全局自动刷新Token的拦截器
  3. 3 */
  4. 4 public class TokenInterceptor implements Interceptor {
  5. 5
  6. 6 @Override
  7. 7 public Response intercept(Chain chain) throws IOException {
  8. 8 Request request = chain.request();
  9. 9 Response response = chain.proceed(request);
  10. 10 LogUtil.print("response.code=" + response.code());
  11. 11
  12. 12 if (isTokenExpired(response)) {//根据和服务端的约定判断token过期
  13. 13 LogUtil.print("静默自动刷新Token,然后重新请求数据");
  14. 14 //同步请求方式,获取最新的Token
  15. 15 String newSession = getNewToken();
  16. 16 //使用新的Token,创建新的请求
  17. 17 Request newRequest = chain.request()
  18. 18 .newBuilder()
  19. 19 .header("Cookie", "JSESSIONID=" + newSession)
  20. 20 .build();
  21. 21 //重新请求
  22. 22 return chain.proceed(newRequest);
  23. 23 }
  24. 24 return response;
  25. 25 }
  26. 26
  27. 27 /**
  28. 28 * 根据Response,判断Token是否失效
  29. 29 *
  30. 30 * @param response
  31. 31 * @return
  32. 32 */
  33. 33 private boolean isTokenExpired(Response response) {
  34. 34 if (response.code() == 404) {
  35. 35 return true;
  36. 36 }
  37. 37 return false;
  38. 38 }
  39. 39
  40. 40 /**
  41. 41 * 同步请求方式,获取最新的Token
  42. 42 *
  43. 43 * @return
  44. 44 */
  45. 45 private String getNewToken() throws IOException {
  46. 46 // 通过一个特定的接口获取新的token,此处要用到同步的retrofit请求
  47. 47 Response_Login loginInfo = CacheManager.restoreLoginInfo(BaseApplication.getContext());
  48. 48 String username = loginInfo.getUserName();
  49. 49 String password = loginInfo.getPassword();
  50. 50
  51. 51 LogUtil.print("loginInfo=" + loginInfo.toString());
  52. 52 Call<Response_Login> call = WebHelper.getSyncInterface().synclogin(new Request_Login(username, password));
  53. 53 loginInfo = call.execute().body();
  54. 54 LogUtil.print("loginInfo=" + loginInfo.toString());
  55. 55
  56. 56 loginInfo.setPassword(password);
  57. 57 CacheManager.saveLoginInfo(loginInfo);
  58. 58 return loginInfo.getSession();
  59. 59 }
  60. 60 }
复制代码

然后配置下OkHttp

  1. HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
  2. logging.setLevel(HttpLoggingInterceptor.Level.BODY);
  3. OkHttpClient client = new OkHttpClient.Builder()
  4. .connectTimeout(15, TimeUnit.SECONDS)
  5. .readTimeout(300, TimeUnit.SECONDS)
  6. .writeTimeout(300, TimeUnit.SECONDS)
  7. .cache(new Cache(FileConstants.HTTP_CACHE_DIR, FileConstants.CACHE_SIZE))
  8. .addInterceptor(interceptor)
  9. // .addInterceptor(new MockInterceptor())
  10. .addInterceptor(new TokenInterceptor())
  11. // .addInterceptor(new RetryIntercepter(3))
  12. .addInterceptor(logging)
  13. .build();
复制代码



回复

使用道具 举报