React Native中Axios请求JWT鉴权GraphQL接口报未授权错误
问题根因(按出现概率从高到低排序)
- 凭证读取优先级冲突:从返回的请求对象可见,Axios默认开启了
withCredentials: true,会自动携带对应域下的所有Cookie。如果后端JWT校验逻辑优先读取Cookie中的Token,而本地10.0.2.2域下存了过期/无效的旧Token Cookie,会直接返回授权失败。Insomnia默认不会自动携带无关Cookie,因此会读取Authorization头中的有效Token正常返回结果。 - Axios版本兼容Bug:0.27.2版本的Axios在React Native环境下存在已知问题,拦截器中设置的自定义请求头在开启withCredentials时,可能出现「Axios内部记录头已存在,但实际网络请求未真正发送」的情况。你打印的
_headers是Axios内部维护的待发送列表,不是实际发出的请求头,不能作为头已正确传递的依据。 - Token携带不可见特殊字符:React Native本地存储(AsyncStorage/MMKV等)保存Token时,可能因为存值逻辑问题混入换行符、零宽空格等不可见字符。手动复制Token到Insomnia时,系统剪贴板会自动过滤末尾的特殊字符,因此Insomnia请求正常,但Axios实际请求时携带了带特殊字符的无效Token,后端JWT解析失败。
- 请求头大小写兼容问题:React Native底层网络库会自动将自定义请求头转为全小写(你打印的待发送头中
authorization为全小写),如果后端自定义头解析逻辑硬编码匹配大写开头的Authorization,会读取不到Token。标准HTTP头是大小写不敏感的,这类问题通常出现在非规范的自定义解析代码中。
修复方案(按顺序验证)
- 关闭withCredentials排除Cookie干扰
修改Axios实例初始化配置,显式关闭withCredentials:
修改后先测试请求,如果恢复正常说明是Cookie优先级问题。后续如果需要保留Cookie传递能力,调整后端Token校验逻辑,优先读取Authorization头中的凭证即可。const api = axios.create({ baseURL: config.API_URI, withCredentials: false, // 新增该行 }); - 调整Axios版本+头设置逻辑
如果第一步无效,将Axios升级到0.28.0+版本,或降级到稳定版0.24.5,避开0.27.x的RN兼容Bug。同时修改拦截器的头设置逻辑,适配RN的头转换规则,同时对Token做去空白处理:api.interceptors.request.use((config: AxiosRequestConfig) => { const { token, pushNotificationToken } = store.getState().user; config.headers = { ...config.headers, // 用小写key设置头,同时trim掉Token首尾的空白、特殊字符 authorization: `Bearer ${token?.trim()}`, pushnotificationtoken: pushNotificationToken || '', }; return config; }); - 校验Token实际值
在请求拦截器中打印完整Token的长度、首尾字符,和Insomnia中使用的有效Token逐字对比,确认不存在不可见字符。如果存在特殊字符,修改Token存储逻辑,存值前统一做trim、过滤不可见字符处理。 - 后端兼容小写请求头
如果以上方案都无效,修改后端JWT解析逻辑,读取请求头时统一做大小写兼容:
避免大小写不匹配导致的Token读取失败。// 后端Node服务示例 const authHeader = req.headers['authorization'] || req.headers['Authorization']; const token = authHeader?.replace(/^Bearer\s+/, '');
内容的提问来源于stack exchange,提问作者aneto
相关产品推荐
相关产品推荐

