You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Expo SecureStore在iOS生产环境丢失JWT令牌问题求助

问题:Expo SecureStore存储JWT令牌在iOS生产环境中莫名丢失

我使用Expo的SecureStore存储JWT令牌,Android端运行正常,但iOS生产环境下令牌会突然丢失,用户需要重新登录。此前用AsyncStorage存储时也存在同样问题,查阅资料得知SecureStore通过keychain服务以kSecClassGenericPassword类型存储数据,安全性更高,但更换后iOS仍会删除令牌。

存储JWT的代码如下:

export const login = createAsyncThunk(
  "auth/login",
  async (userCredentials, thunkAPI) => {
    const notifToken = await SecureStore.getItemAsync("notification_token");
     
    try {
      let loginData = {
        email: userCredentials.mail,
        password: userCredentials.password,
      };

      if (notifToken) {
        loginData = {
          ...loginData,
          notif_token: notifToken,
        };
      }

      const response = await axios.post(ENDPOINTS.loginToken, loginData, {
        headers: {
          "Content-Type": "application/json",
        },
      });
      await SecureStore.setItemAsync("access_token", response.data.access);

      await SecureStore.setItemAsync("refresh_token", response.data.refresh);

      return response.data;
    } catch (error) {
      await SecureStore.clear();
      return thunkAPI.rejectWithValue(error.response.data);
    }
  }
);
排查与解决方法
  • 检查iOS keychain访问权限配置
    iOS生产环境下,keychain访问权限需正确配置。在app.json中添加keychain权限组,替换为你的应用实际bundle ID:

    {
      "expo": {
        "ios": {
          "entitlements": {
            "keychain-access-groups": ["$(AppIdentifierPrefix)com.your.app.bundle"]
          }
        }
      }
    }
    

    $(AppIdentifierPrefix)会自动填充开发者账号前缀,无需手动修改。

  • 修正SecureStore.clear()的误触发
    代码中登录失败的catch块调用了SecureStore.clear(),会清空所有存储内容。若登录请求因网络波动等原因偶尔失败,会直接删除已有的令牌。建议仅清除登录相关的令牌项:

    catch (error) {
      await SecureStore.deleteItemAsync("access_token");
      await SecureStore.deleteItemAsync("refresh_token");
      return thunkAPI.rejectWithValue(error.response.data);
    }
    
  • 指定令牌存储的访问属性
    使用SecureStore.setItemAsync时,通过options参数明确keychain存储属性,设置accessible为SecureStore.WHEN_UNLOCKED_THIS_DEVICE_ONLY,降低系统自动清理概率:

    await SecureStore.setItemAsync("access_token", response.data.access, {
      accessible: SecureStore.WHEN_UNLOCKED_THIS_DEVICE_ONLY
    });
    await SecureStore.setItemAsync("refresh_token", response.data.refresh, {
      accessible: SecureStore.WHEN_UNLOCKED_THIS_DEVICE_ONLY
    });
    

    该配置确保仅设备解锁时可访问令牌,且不会同步到iCloud。

  • 排查iOS系统自动清理机制
    iOS存储空间不足或用户开启“卸载未使用的应用”时,可能影响令牌存储。可提醒用户关闭自动卸载功能,同时在应用启动时检查令牌是否存在,若缺失则触发静默刷新(需有令牌刷新机制)。

  • 升级Expo SDK版本
    部分旧版Expo SDK存在SecureStore相关bug,升级至最新稳定版可能解决问题。

内容的提问来源于stack exchange,提问作者Sahak 12

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 05:22:35