反应导航:带有身份验证的深层链接

Zum*_*uma 9 deep-linking react-native react-navigation

我正在构建一个具有react-native和react-navigation库的移动应用程序,用于管理我的应用程序中的导航。现在,我的应用看起来像这样:

App [SwitchNavigator]
    Splash [Screen]
    Auth [Screen]
    MainApp [StackNavigator]
        Home [Screen]            (/home)
        Profile [Screen]         (/profile)
        Notifications [Screen]   (/notifications)
Run Code Online (Sandbox Code Playgroud)

我已经将“深层链接”与上述屏幕HomeProfile和的模式集成在一起Notifications,并且按预期工作。我面临的问题是使用深层链接时如何管理用户的身份验证。现在,无论何时打开深层链接(myapp://profile例如),无论我是否通过身份验证,该应用程序都会将我带到屏幕上。我想要它做的是先检查AsyncStorage是否有一个userToken,如果没有,或者它不再有效,然后在Auth屏幕上重定向。

我以与此处所述几乎完全相同的方式设置了身份验证流程。因此,当我的应用程序启动时,Splash屏幕会检查用户电话中是否存在有效令牌,然后将其发送到Auth屏幕或Home屏幕上。

我目前想出的唯一解决方案是将每个深层链接指向,对Splash用户进行身份验证,然后解析该链接以导航至正确的屏幕。例如,当用户打开时myapp://profile,我打开应用程序Splash,验证令牌,然后解析url(/profile),最后重定向到AuthProfile

这是这样做的好方法,还是反应导航提供了更好的方法?他们网站上的“ 深层链接”页面有点亮。

谢谢您的帮助 !

nhu*_*ann 5

我的设置与您的设置相似。我遵循了身份验证流程·反应导航SplashScreen-博览会文档来设置我的Auth流,因此令我有些失望的是,使深层链接也流经它也是一个挑战。我可以通过自定义主开关导航器来使此工作正常进行,该方法类似于您所说的当前解决方案。我只是想分享我的解决方案,所以有一个具体的例子说明如何开始工作。我已经像这样设置了主开关导航器(也正在使用TypeScript,所以如果它们不熟悉,请忽略类型定义):

const MainNavigation = createSwitchNavigator(
  {
    SplashLoading,
    Onboarding: OnboardingStackNavigator,
    App: AppNavigator,
  },
  {
    initialRouteName: 'SplashLoading',
  }
);

const previousGetActionForPathAndParams =
  MainNavigation.router.getActionForPathAndParams;

Object.assign(MainNavigation.router, {
  getActionForPathAndParams(path: string, params: any) {
    const isAuthLink = path.startsWith('auth-link');

    if (isAuthLink) {
      return NavigationActions.navigate({
        routeName: 'SplashLoading',
        params: { ...params, path },
      });
    }

    return previousGetActionForPathAndParams(path, params);
  },
});

export const AppNavigation = createAppContainer(MainNavigation);
Run Code Online (Sandbox Code Playgroud)

您想通过身份验证流进行路由的任何深层链接都必须以开头auth-link,或者您选择以其开头的任何内容。这里是什么SplashLoading样子:

export const SplashLoading = (props: NavigationScreenProps) => {
  const [isSplashReady, setIsSplashReady] = useState(false);

  const _cacheFonts: CacheFontsFn = fonts =>
    fonts.map(font => Font.loadAsync(font as any));

  const _cacheSplashAssets = () => {
    const splashIcon = require(splashIconPath);
    return Asset.fromModule(splashIcon).downloadAsync();
  };

  const _cacheAppAssets = async () => {
    SplashScreen.hide();
    const fontAssetPromises = _cacheFonts(fontMap);
    return Promise.all([...fontAssetPromises]);
  };

  const _initializeApp = async () => {
    // Cache assets
    await _cacheAppAssets();

    // Check if user is logged in
    const sessionId = await SecureStore.getItemAsync(CCSID_KEY);

      // Get deep linking params
    const params = props.navigation.state.params;
    let action: any;

    if (params && params.routeName) {
      const { routeName, ...routeParams } = params;
      action = NavigationActions.navigate({ routeName, params: routeParams });
    }

    // If not logged in, navigate to Auth flow
    if (!sessionId) {
      return props.navigation.dispatch(
        NavigationActions.navigate({
          routeName: 'Onboarding',
          action,
        })
      );
    }

    // Otherwise, navigate to App flow
    return props.navigation.navigate(
      NavigationActions.navigate({
        routeName: 'App',
        action,
      })
    );
  };

  if (!isSplashReady) {
    return (
      <AppLoading
        startAsync={_cacheSplashAssets}
        onFinish={() => setIsSplashReady(true)}
        onError={console.warn}
        autoHideSplash={false}
      />
    );
  }

  return (
    <View style={{ flex: 1 }}>
      <Image source={require(splashIconPath)} onLoad={_initializeApp} />
    </View>
  );
};
Run Code Online (Sandbox Code Playgroud)

我使用routeName查询参数创建了深层链接,查询参数是执行身份验证检查后导航到的屏幕的名称(显然,您可以添加所需的任何其他查询参数)。由于我的SplashLoading屏幕可以处理所有字体/资产的加载以及身份验证的检查,因此我需要每个深层链接来进行路由。我遇到的问题是,我将手动从多任务处理中退出应用程序,点击深层链接网址,并且由于绕过深层链接SplashLoading而无法加载字体而导致应用程序崩溃。

上面的方法声明了一个action变量,如果未设置该变量将无效。如果routeName查询参数不是undefined,则设置action变量。这样一来,一旦Switch路由器基于auth(OnboardingApp)决定采用哪个路径,该路由就会获得子操作,并routeName在退出auth / splash加载流程后导航至。

这是我创建的示例链接,可以在此系统上正常运行: exp://192.168.1.7:19000/--/auth-link?routeName=ForgotPasswordChange&cacheKey=a9b3ra50-5fc2-4er7-b4e7-0d6c0925c536

希望图书馆作者将来将此功能作为本机支持的功能,这样就不必进行黑客攻击了。我也很想知道您的想法!