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

Flutter Android/iOS集成ORY Login遇反序列化错误求工作示例

Flutter集成ORY Login的问题与工作示例

问题说明

尝试在Flutter Android/iOS应用中集成ORY Login功能,未找到移动端相关示例,参考Web端代码编写后无法正常运行,调用await _ory.createNativeLoginFlow()时出现反序列化错误。

问题排查与修正要点

  • Dio客户端配置:移动端需确保Dio正确管理Cookie,适配ORY的会话机制
  • createNativeLoginFlow参数:该接口需传入returnTo等必要参数,否则响应结构不符合客户端预期,触发反序列化失败
  • 流程完整性:登录流程需先初始化Flow,再提交认证信息,不能直接跳过步骤调用updateLoginFlow

可运行的工作示例代码

import 'dart:developer';
import 'package:dio/dio.dart';
import 'package:dio/native_imp.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:ory_client/ory_client.dart';

class AuthService {
  final FrontendApi _ory;
  Session? _identity;
  String? _loginFlowId;

  AuthService(Dio dio) : _ory = OryClient(dio: dio).getFrontendApi();

  static AuthService init() {
    const baseUrl = "https://{your-slug}.projects.oryapis.com";

    final options = BaseOptions(
      baseUrl: baseUrl,
      connectTimeout: const Duration(seconds: 10),
      receiveTimeout: const Duration(seconds: 5),
      headers: {
        "Accept": "application/json",
        "Content-Type": "application/json",
      },
      validateStatus: (status) => status != null && status < 500,
    );

    final dio = DioForNative(options);
    // 移动端启用Cookie管理,维持ORY会话
    dio.interceptors.add(CookieManager(PersistCookieJar()));

    return AuthService(dio);
  }

  Future<bool> isAuthenticated() async {
    try {
      final resp = await _ory.toSession();
      if (resp.statusCode == 200) {
        _identity = resp.data;
        return true;
      }
      return false;
    } catch (error) {
      log("认证状态检查失败: $error");
      return false;
    }
  }

  Future<void> initLoginFlow() async {
    try {
      // 传入App跳转Scheme,符合Native Flow要求
      final resp = await _ory.createNativeLoginFlow(
        returnTo: "com.your.app://auth-callback", // 替换为你的App自定义Scheme
      );
      if (resp.statusCode == 200) {
        _loginFlowId = resp.data?.id;
        log("登录Flow初始化成功: ${resp.data?.id}");
      } else {
        log("登录Flow初始化失败: ${resp.statusMessage}");
      }
    } catch (error) {
      log("登录Flow初始化异常: $error");
    }
  }

  Future<bool> submitLogin(String email, String password) async {
    if (_loginFlowId == null) {
      log("请先调用initLoginFlow初始化登录流程");
      return false;
    }

    try {
      final resp = await _ory.updateLoginFlow(
        flow: _loginFlowId!,
        updateLoginFlowBody: UpdateLoginFlowBody(
          passwordIdentifier: email,
          password: password,
          method: "password",
        ),
      );

      if (resp.statusCode == 200) {
        await isAuthenticated();
        log("登录成功");
        return true;
      } else {
        log("登录失败: ${resp.data?.error?.message}");
        return false;
      }
    } catch (error) {
      log("登录提交异常: $error");
      return false;
    }
  }

  Future<void> logout() async {
    try {
      final resp = await _ory.performNativeLogout(
        performNativeLogoutBody: const PerformNativeLogoutBody(),
      );
      if (resp.statusCode == 200 && resp.data?.logoutToken != null) {
        final logoutResp = await _ory.updateLogoutFlow(
          token: resp.data!.logoutToken!,
        );
        if (logoutResp.statusCode == 200) {
          _identity = null;
          log("登出成功");
        }
      }
    } catch (error) {
      log("登出异常: $error");
    }
  }

  Session? get identity => _identity;
}

使用说明

  1. 替换baseUrl中的{your-slug}为你的ORY项目专属Slug
  2. 替换returnTo中的com.your.app://auth-callback为你的App自定义Scheme(需在AndroidManifest.xml和Info.plist中提前配置)
  3. 调用流程:先执行initLoginFlow()初始化登录流程,再调用submitLogin(email, password)提交账号密码信息

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 09:38:18