PicaComic 第三方登录集成:Google/Apple 账号接入

PicaComic 第三方登录集成:Google/Apple 账号接入

登录功能现状分析

PicaComic作为跨平台漫画应用,当前登录系统主要围绕各漫画源独立实现。在lib/pages/ehentai/eh_login_page.dart中可看到E-hentai的Cookie登录方式,而lib/pages/nhentai/login.dart则实现了nhentai的账号密码登录。这种分散式登录架构导致用户需要记忆多个平台账号,且无法实现跨源数据同步。

第三方登录架构设计

为解决多源登录痛点,建议采用以下三层架构实现统一认证:

mermaid

核心实现文件规划:

  • 认证抽象层:lib/foundation/auth/auth_manager.dart
  • Google登录:lib/foundation/auth/google_auth.dart
  • Apple登录:lib/foundation/auth/apple_auth.dart
  • 账号关联:lib/foundation/auth/account_linker.dart

平台适配实现指南

Android平台配置

  1. android/app/src/main/AndroidManifest.xml添加Google认证配置:
<meta-data
    android:name="com.google.android.gms.version"
    android:value="@integer/google_play_services_version" />
<activity
    android:name="com.google.android.gms.auth.api.signin.internal.SignInHubActivity"
    android:screenOrientation="portrait"
    android:theme="@android:style/Theme.Translucent.NoTitleBar" />
  1. google-services.json放置于android/app/目录,包含服务器客户端ID和API密钥

iOS平台配置

  1. iOS/Runner/Info.plist添加权限声明:
<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleTypeRole</key>
        <string>Editor</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>com.googleusercontent.apps.YOUR_CLIENT_ID</string>
        </array>
    </dict>
</array>
<key>ASAuthorizationAppleIDProvider</key>
<dict>
    <key>ASAuthorizationScopeEmail</key>
    <true/>
    <key>ASAuthorizationScopeFullName</key>
    <true/>
</dict>
  1. 在Xcode中启用Sign in with Apple能力,配置Runner.xcodeproj的Signing & Capabilities

核心代码实现

认证管理器

创建lib/foundation/auth/auth_manager.dart作为统一入口:

class AuthManager {
  final Map<AuthType, AuthProvider> _providers = {
    AuthType.google: GoogleAuthProvider(),
    AuthType.apple: AppleAuthProvider(),
  };

  Future<UserCredential> signInWith(AuthType type) async {
    final provider = _providers[type];
    if (provider == null) throw UnsupportedError('未支持的登录方式');
    
    final credential = await provider.signIn();
    await _syncWithComicSources(credential);
    return credential;
  }
  
  Future<void> _syncWithComicSources(UserCredential credential) async {
    // 实现与各漫画源的账号关联逻辑
    await EHentaiAccountLinker().link(credential);
    await NHentaiAccountLinker().link(credential);
  }
}

Google登录实现

在lib/foundation/auth/google_auth.dart中集成google_sign_in插件:

class GoogleAuthProvider implements AuthProvider {
  final GoogleSignIn _googleSignIn = GoogleSignIn(
    scopes: ['email', 'profile'],
    clientId: 'YOUR_WEB_CLIENT_ID',
  );

  @override
  Future<UserCredential> signIn() async {
    try {
      final account = await _googleSignIn.signIn();
      if (account == null) throw AuthCancelledException();
      
      final auth = await account.authentication;
      return UserCredential(
        provider: AuthType.google,
        idToken: auth.idToken,
        userInfo: UserInfo(
          id: account.id,
          name: account.displayName,
          email: account.email,
          avatarUrl: account.photoUrl,
        ),
      );
    } catch (e) {
      Log.error('Google登录失败', e);
      throw AuthFailedException(e.toString());
    }
  }
}

Apple登录实现

在lib/foundation/auth/apple_auth.dart中实现Apple登录:

class AppleAuthProvider implements AuthProvider {
  @override
  Future<UserCredential> signIn() async {
    if (!Platform.isIOS) throw UnsupportedError('仅iOS支持Apple登录');
    
    final appleCredential = await SignInWithApple.getAppleIDCredential(
      scopes: [AppleIDAuthorizationScopes.email, AppleIDAuthorizationScopes.fullName],
    );
    
    return UserCredential(
      provider: AuthType.apple,
      idToken: appleCredential.identityToken,
      userInfo: UserInfo(
        id: appleCredential.userIdentifier,
        name: '${appleCredential.givenName} ${appleCredential.familyName}',
        email: appleCredential.email,
      ),
    );
  }
}

登录界面集成

修改lib/pages/auth_page.dart添加第三方登录按钮:

Column(
  children: [
    // 现有登录表单保持不变
    _buildTraditionalLoginForm(),
    
    Divider(height: 30, indent: 40, endIndent: 40),
    
    // 新增第三方登录区域
    Text('其他登录方式'),
    SizedBox(height: 16),
    Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        IconButton(
          icon: Image.asset('images/google_icon.png', width: 40),
          onPressed: () => AuthManager().signInWith(AuthType.google),
        ),
        SizedBox(width: 24),
        if (Platform.isIOS)
          IconButton(
            icon: Image.asset('images/apple_icon.png', width: 40),
            onPressed: () => AuthManager().signInWith(AuthType.apple),
          ),
      ],
    ),
  ],
)

所需图标资源应放置在images/google_icon.png和images/apple_icon.png,建议使用SVG格式确保多分辨率适配。

账号安全与数据同步

为保障认证安全,需在lib/network/app_dio.dart中添加Token拦截器:

class AuthInterceptor extends Interceptor {
  @override
  Future<void> onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
    final token = await AuthManager().getCurrentToken();
    if (token != null) {
      options.headers['Authorization'] = 'Bearer $token';
    }
    handler.next(options);
  }
}

数据同步流程可参考lib/network/net_fav_to_local.dart中的收藏同步逻辑,实现跨设备的阅读进度和收藏数据统一。

实现效果预览

成功集成后,用户将在登录界面看到新增的第三方登录选项:

第三方登录界面

登录成功后,系统会自动关联已有漫画源账号,用户可在lib/pages/accounts_page.dart中查看和管理所有已关联的账号。

兼容性与测试策略

平台最低版本要求测试重点
AndroidAPI 21+Google Play服务版本兼容性
iOSiOS 13+系统设置中的Apple ID授权状态
WebChrome 70+跨域登录回调处理

建议在test/widget_test.dart中添加认证流程测试,确保登录状态正确持久化到lib/foundation/history.dart和本地存储。

后续优化方向

  1. 实现OAuth账号的自动注册流程,减少用户操作步骤
  2. 添加生物识别二次验证,增强敏感操作安全性
  3. 开发账号切换功能,支持多身份快速切换
  4. 集成 Firebase Authentication 实现更完善的账号管理

通过这套第三方登录方案,PicaComic将实现真正意义上的一站式漫画阅读体验,大幅降低用户使用门槛,为后续实现跨源数据聚合奠定基础。详细API文档可参考doc/comic_source.md中的认证接口规范。

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值