React Native中AWS Amplify鉴权token失效时如何自动跳转回登录页?
实现方案
步骤1:配置全局Navigation引用
解决拦截器中无法获取组件内navigation参数的问题,使用React Navigation官方提供的全局引用方案:
- 新建
navigation.js文件存储全局导航引用:
import { createNavigationContainerRef } from '@react-navigation/native'; export const navigationRef = createNavigationContainerRef();
- 给项目根组件的
NavigationContainer绑定该引用:
import { navigationRef } from './navigation'; // 其他引入省略 function App() { return ( <NavigationContainer ref={navigationRef}> {/* 原有导航栈/标签栏配置保持不变 */} </NavigationContainer> ) }
步骤2:封装axios实例并添加全局拦截器
统一处理所有请求的token注入、401状态码响应逻辑,避免每个请求重复写鉴权代码:
新建apiClient.js文件:
import axios from 'axios'; import { Auth } from 'aws-amplify'; import { navigationRef } from './navigation'; // 替换为你项目中登录页对应的路由名称 const LOGIN_ROUTE = 'Login'; // 创建自定义axios实例,可统一配置基础接口域名、超时时间等公共参数 const apiClient = axios.create({ baseURL: '你的接口基础地址', timeout: 10000, }); // 请求拦截器:自动给所有请求注入Authorization头 apiClient.interceptors.request.use( async (config) => { try { const session = await Auth.currentSession(); const token = session.getAccessToken().getJwtToken(); if (token) { config.headers.Authorization = `Bearer ${token}`; } } catch (e) { // 本地会话失效直接触发未授权逻辑 handleUnauthorized(); return Promise.reject(e); } return config; }, (error) => Promise.reject(error) ); // 响应拦截器:统一捕获401未授权响应 apiClient.interceptors.response.use( (response) => response, async (error) => { if (error.response?.status === 401) { handleUnauthorized(); } return Promise.reject(error); } ); // 统一未授权处理逻辑 const handleUnauthorized = async () => { // 若当前已在登录页,不重复跳转 const currentRoute = navigationRef.getCurrentRoute()?.name; if (currentRoute === LOGIN_ROUTE) return; try { // 清理AWS Amplify本地残留的无效会话 await Auth.signOut(); } catch (e) { console.log('会话清理失败', e); } // 重置导航栈跳转到登录页,避免用户按返回键回到之前的鉴权页面 navigationRef.reset({ index: 0, routes: [{ name: LOGIN_ROUTE }], }); }; export default apiClient;
步骤3:改造原有请求逻辑
后续所有接口请求直接使用封装好的apiClient即可,无需再手动调用getAccessToken、添加Authorization头:
import apiClient from './apiClient'; function getSomething() { apiClient.get('<你的接口地址>') .then(response => { console.log(response.data) setData(response.data); }) .catch(error => { // 此处仅需处理401之外的业务错误,401逻辑已全局处理 console.log(JSON.stringify(error)); }); };
注意事项
- 请将代码中的
LOGIN_ROUTE替换为你项目中登录页实际配置的路由名称 Auth.currentSession()本身已经内置了未过期refresh token的自动刷新逻辑,仅当refresh token也过期时才会抛出错误,该方案已覆盖会话过期的所有场景- 如果你不想使用全局导航引用,也可以在每个页面的请求catch分支中判断401状态码,再调用组件传入的
navigation参数跳转,不过该方案会产生大量重复代码,更推荐全局拦截方案
内容的提问来源于stack exchange,提问作者user12314098
相关产品推荐
相关产品推荐

