HarmonyOS 鸿蒙Next如何实现类似iOS token无感刷新功能

发布于 1周前 作者 sinazl 来自 鸿蒙OS

HarmonyOS 鸿蒙Next如何实现类似iOS token无感刷新功能

实现token无感刷新为了优化用户体验,当token过期时不需要用户跳回登录页重新登录,而是当token失效时,进行拦截,发送刷新token的请求,获取最新的token进行覆盖,让用户感受不到token已经过期

想实现的方案:在相应其中拦截,判断token返回过期后,调用刷新token的接口,然后自动重连刚刚token过期接口

3 回复

Demo如下:

import rcp from '@hms.collaboration.rcp';
import { BusinessError } from '@kit.BasicServicesKit';
import { hilog } from '@kit.PerformanceAnalysisKit';

//拦截器接收数据对象
class ResponseCache {
  private readonly cache: Record<string, rcp.Response> = {};

  getResponse(url: string): rcp.Response {
    return this.cache[url];
  }

  setResponse(url: string, response: rcp.Response): void {
    this.cache[url] = response;
  }
}

let storage: LocalStorage = new LocalStorage();
async function refreshToken(): Promise<string> {
  // 发送请求获取并返回token
  const response = await rcp.createSession().post('https://your-server.com/refresh-token');
  if (response.statusCode === 200) {
    // 注意这里需要返回实际获取的token
    return 'response.refreshToken';
  } else {
    throw new Error('Failed to refresh token');
  }
}


//自定义拦截器
class ResponseCachingInterceptor implements rcp.Interceptor {
  private readonly cache: ResponseCache;

  constructor(cache: ResponseCache) {
    this.cache = cache;
  }

  //拦截器获取数据方法定义
  intercept(context: rcp.RequestContext, next: rcp.RequestHandler): Promise<rcp.Response> {
    // 缓存
    const url = context.request.url.href;
    const responseFromCache = this.cache.getResponse(url);
    if (responseFromCache) {
      return Promise.resolve(responseFromCache);
    }

    const promise = next.handle(context);
    promise.then((resp) => {
      if (resp.statusCode == 401) { // Token 过期
        try {
          refreshToken().then((newToken) => {
            if (context.request.headers) {
              context.request.headers.authorization = 'Bearer ' + newToken
              // 重新用新的token发送原始请求
              const retryResponse = next.handle(context);
              retryResponse.then(res => {
                return retryResponse
              })
            }
          })
        } catch (error) {
          // 处理重新发送失败的请求
        }
      }
      this.cache.setResponse(url, resp);
    });
    return promise;
  }
}

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';
  testUrl = "https://www.baidu.com"

  //get请求方式获取数据
  rcpGetData() {
    let testUrl = this.testUrl
    //定义通信会话对象
    const sessionConfig = rcp.createSession();
    //get请求
    sessionConfig.get(testUrl).then((response) => {
      hilog.info(0x0000, 'testTag', "test---------" + JSON.stringify(response));
      //页面展示请求结果
      AlertDialog.show(
        {
          title: 'request接口回调结果',
          message: '请求网站:' + testUrl + '\n\n' + 'Callback Data: ' + JSON.stringify(response),
        })
    }).catch((err: BusinessError) => {
      AlertDialog.show(
        {
          title: 'request接口回调结果',
          message: '请求失败,错误信息:' + err.data,
        })
      hilog.error(0x0000, 'testTag', "test err:" + JSON.stringify(err));
    });
  }


  //拦截器
  getDataByInterceptor() {
    const cache = new ResponseCache();
    const session = rcp.createSession({
      interceptors: [new ResponseCachingInterceptor(cache)]
    });

    session.get(this.testUrl).then((response) => {
      hilog.info(0x0000, 'testTag', 'get requestData :' + JSON.stringify(response.request))
      hilog.info(0x0000, 'testTag', 'get headersData :' + JSON.stringify(response.headers))
    }).catch((err: BusinessError) => {
      hilog.info(0x0000, 'testTag', `err: err code is ${err.code}, err message is ${err.message}`);
    });
  }

  build() {
    Row() {
      Column() {
        //get请求方式获取数据
        Button('getData')
          .onClick(() => {
            this.rcpGetData();
          })
          .type(ButtonType.Capsule)
          .margin({ top: 4 })
          .backgroundColor('#ff1198ee')
          .width('67%')
          .height('4%')
      }
      .width('100%')
    }
    .height('100%')
  }
}

HarmonyOS 鸿蒙Next要实现类似iOS的token无感刷新功能,可以通过以下方式实现:

首先,鸿蒙系统需支持在API接口请求时自动携带token进行身份验证。当token过期导致请求失败(如返回401状态码)时,系统应能自动拦截这一错误响应。

接着,系统可利用存储的refresh_token,在后台静默地调用刷新token的接口。成功获取新token后,系统需自动替换掉本地存储的过期token,并重新尝试之前失败的请求,确保用户无感知地完成整个过程。

此外,为确保刷新token的有效性,系统还需处理refresh_token过期的情况。一旦refresh_token也过期,系统应清除所有相关token信息,并引导用户重新登录。

请注意,实现该功能需后端配合提供刷新token的接口,并返回必要的token信息。同时,前端需妥善管理token的存储和更新逻辑。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部