在 flutter 中使用 Go Router 和 BLoC 进行身份验证

问题描述 投票:0回答:1

我在 Web 应用程序中使用 Go Router 和 BLoC 来管理用户会话。我正在寻找的是,在输入某个路线时,能够验证用户是否已通过身份验证。在 BLoC 内部,我有一个函数来验证令牌是否存在(它返回“false”或“true”)。 我的问题是,在刷新页面的情况下,先执行路径逻辑,然后执行BLoC逻辑。然后,如果已经有用户登录,则路径防护将采用“isAuth”的初始状态,该状态为 false,但如果它为 true,因为令牌确实存在。 我能做什么?

路由器:

final GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();

class AppRouter {
  final GoRouter router = GoRouter(
    initialLocation: Uri.base.toString().replaceFirst(Uri.base.origin, ''),
    navigatorKey: _navigatorKey,
    routes: <RouteBase>[
      GoRoute(
        path: Routes.home,
        builder: (BuildContext context, GoRouterState state) =>
            BlocProvider<SignInCubit>.value(
          value: locator<SignInCubit>(),
          child: const SignInScreen(),
        ),
      ),
      GoRoute(
        path: Routes.paymentConfirmation,
        builder: (BuildContext context, GoRouterState state) =>
            BlocProvider<PaymentConfirmationCubit>(
          create: (_) => locator<PaymentConfirmationCubit>(),
          child: const PaymentConfirmation(),
        ),
        redirect: (BuildContext context, _) {
          if (context.read<SessionBloc>().state.isAuth) {
            return null;
          }
          return Routes.home;
        },
      ),
      GoRoute(
        path: Routes.otpCodeValidation,
        builder: (BuildContext context, GoRouterState state) =>
            BlocProvider<OtpCodeCubit>.value(
          value: locator<OtpCodeCubit>(),
          child: const OtpCodeValidation(),
        ),
      ),
      GoRoute(
        path: Routes.paymentValidation,
        builder: (BuildContext context, GoRouterState state) =>
            const PaymentValidation(),
      ),
      GoRoute(
        path: Routes.transactionsList,
        builder: (BuildContext context, GoRouterState state) =>
            const TransactionsList(),
      ),
      GoRoute(
        path: Routes.transactionDetail,
        builder: (BuildContext context, GoRouterState state) =>
            const TransactionDetail(),
      ),
    ],
  );
}

区块:

class SessionBloc extends Bloc<SessionEvent, SessionState> {
  SessionBloc({
    required this.validateTokenUseCase,
    required this.signInUseCase,
  }) : super(SessionState(user: User.empty())) {
    on<SessionStarted>(_onSessionStarted);
  }

  final ValidateTokenUseCase validateTokenUseCase;
  final SignInUseCase signInUseCase;

  Future<void> _onSessionStarted(
      SessionStarted event, Emitter<SessionState> emit) async {
    emit(state.copyWith(isLoading: true));
    try {
      final bool isValid = await validateTokenUseCase.call();
      emit(state.copyWith(isLoading: false, isAuth: isValid));
      // emit(state.copyWith(user: event.user));
    } catch (e) {
      emit(state.copyWith(isLoading: false));
      rethrow;
    }
  }
}

应用程序:

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return BlocProvider<SessionBloc>(
      create: (_) => locator<SessionBloc>()..add(const SessionStarted()),
      child: OKToast(
        child: MaterialApp.router(
          builder: (BuildContext context, Widget? widget) {
            return OKToast(child: widget!);
          },
          debugShowCheckedModeBanner: false,
          theme: appTheme,
          routerConfig: AppRouter().router,
          localizationsDelegates: const <LocalizationsDelegate<dynamic>>[
            GlobalMaterialLocalizations.delegate,
            GlobalCupertinoLocalizations.delegate,
            GlobalWidgetsLocalizations.delegate
          ],
          supportedLocales: LocaleSettings.instance.supportedLocales,
          locale: TranslationProvider.of(context).flutterLocale,
          title: 'Orquestador Pideky Escala',
        ),
      ),
    );
  }
}
flutter authentication flutter-bloc flutter-go-router
1个回答
0
投票

我设法通过将“MaterialApp.router”包装在 BlocListener 中并在 AuthState 更改时刷新路由器(在侦听器指令中)来解决我的问题。像这样:

return MultiBlocProvider(
  providers: <SingleChildWidget>[
    BlocProvider<AuthBloc>(
      create: (_) => locator<AuthBloc>()..add(const VerifyAuth()),
    ),
    BlocProvider<SessionBloc>(
      create: (_) => locator<SessionBloc>()..add(const SessionStarted()),
    ),
  ],
  child: BlocListener<AuthBloc, AuthState>(
      listener: (BuildContext context, AuthState state) {
        router.refresh();
      },
      child: MaterialApp.router(
        builder: (BuildContext context, Widget? widget) {
          return OKToast(child: widget!);
        },
        debugShowCheckedModeBanner: false,
        theme: appTheme,

...rest of the code

显然,需要一个 Provider(在我的例子中是 MultiBlocProvider)来监听更改。

© www.soinside.com 2019 - 2024. All rights reserved.