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

Flutter深度链接配置:同URL不同参数的多路由区分方案

Flutter深度链接路由配置:区分同路由不同参数的功能

不要依赖应用内存中的临时状态(比如你之前用的布尔值),应用重启后状态会丢失,完全不可靠。正确的做法是直接解析URL中的token参数,结合后端校验或前端规则判断对应的功能,以下是具体实现步骤:

1. 配置基础深度链接路由

以常用的go_router为例,定义/click路由并接收token查询参数:

final GoRouter router = GoRouter(
  routes: <RouteBase>[
    GoRoute(
      path: '/click',
      builder: (BuildContext context, GoRouterState state) {
        // 从路由状态中提取token参数
        final String? token = state.queryParameters['token'];
        return ClickHandlerPage(token: token);
      },
    ),
    // 配套路由:邮箱验证页、密码重置页、错误页
    GoRoute(path: '/verify-email', builder: (context, state) => const VerifyEmailPage()),
    GoRoute(path: '/reset-password', builder: (context, state) => const ResetPasswordPage()),
    GoRoute(path: '/error', builder: (context, state) => const ErrorPage()),
  ],
);

2. 解析token并分发功能

推荐优先使用后端校验的方案,安全性更高;如果token有固定格式,也可以直接在前端判断:

方案一:后端校验token类型(推荐)

通过后端接口判断当前token对应的功能类型,避免前端规则被篡改:

class ClickHandlerPage extends StatefulWidget {
  final String? token;
  const ClickHandlerPage({super.key, this.token});

  @override
  State<ClickHandlerPage> createState() => _ClickHandlerPageState();
}

class _ClickHandlerPageState extends State<ClickHandlerPage> {
  @override
  void initState() {
    super.initState();
    _dispatchByToken();
  }

  Future<void> _dispatchByToken() async {
    if (widget.token == null) {
      // 无token参数,跳转错误页
      Navigator.pushReplacementNamed(context, '/error');
      return;
    }

    // 调用后端接口,获取token对应的功能类型
    final TokenTypeResponse response = await AuthApi.checkTokenType(widget.token!);
    switch (response.type) {
      case TokenType.verifyEmail:
        Navigator.pushReplacementNamed(context, '/verify-email', arguments: widget.token);
        break;
      case TokenType.resetPassword:
        Navigator.pushReplacementNamed(context, '/reset-password', arguments: widget.token);
        break;
      default:
        Navigator.pushReplacementNamed(context, '/error');
    }
  }

  @override
  Widget build(BuildContext context) {
    // 等待接口返回时显示加载状态
    return const Scaffold(body: Center(child: CircularProgressIndicator()));
  }
}

// 后端返回的示例模型
enum TokenType { verifyEmail, resetPassword, invalid }
class TokenTypeResponse {
  final TokenType type;
  TokenTypeResponse(this.type);
}

方案二:前端根据token规则判断(仅适用于token有固定格式的场景)

如果你的token有明确格式区分(比如验证token以ver-开头,重置密码token以res-开头),可以直接在前端解析:

Future<void> _dispatchByToken() async {
  if (widget.token == null) {
    Navigator.pushReplacementNamed(context, '/error');
    return;
  }

  final String token = widget.token!;
  if (token.startsWith('ver-')) {
    Navigator.pushReplacementNamed(context, '/verify-email', arguments: token);
  } else if (token.startsWith('res-')) {
    Navigator.pushReplacementNamed(context, '/reset-password', arguments: token);
  } else {
    Navigator.pushReplacementNamed(context, '/error');
  }
}

3. 处理冷启动场景

确保应用冷启动时能正确获取深度链接参数,go_router会自动处理初始链接。如果使用其他路由库,可以在main函数中提前获取初始URI:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // 获取冷启动时的深度链接(需依赖url_launcher或uni_links包)
  final Uri? initialUri = await getInitialUri();
  runApp(MyApp(initialUri: initialUri));
}

关键注意事项

  • 永远不要依赖内存中的临时状态(比如布尔值)来区分功能,应用重启或进程被杀后状态会丢失,URL参数是唯一可靠的来源。
  • 必须对token进行有效性校验,避免恶意链接跳转错误页面。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 20:33:09