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

Flutter+Firebase集成Apple Sign In时DisplayName无法更新至用户记录

解决Flutter Firebase Apple Sign In无法更新DisplayName的问题

问题原因分析

  1. Apple授权限制:Apple仅在用户首次授权登录时返回fullName信息,后续登录不会再返回该字段。如果是重复登录,你的fixDisplayNameFromApple会是空字符串,导致更新无效。
  2. Web端逻辑缺失:当前代码仅处理了移动端的DisplayName更新,Web端通过signInWithPopup获取的用户信息没有做同步处理。
  3. 异步操作未确认:updateDisplayName是异步操作,虽调用了reload,但未确保操作完成后再执行后续逻辑,也没有错误捕获,无法排查更新是否失败。

修复后的代码

import 'dart:convert';
import 'dart:math';

import 'package:crypto/crypto.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:sign_in_with_apple/sign_in_with_apple.dart';

import 'auth_util.dart';

/// 生成加密安全的随机nonce,用于凭证请求
String generateNonce([int length = 32]) {
  final charset =
      '0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._';
  final random = Random.secure();
  return List.generate(length, (_) => charset[random.nextInt(charset.length)])
      .join();
}

/// 返回输入字符串的sha256哈希值(十六进制格式)
String sha256ofString(String input) {
  final bytes = utf8.encode(input);
  final digest = sha256.convert(bytes);
  return digest.toString();
}

Future<UserCredential> appleSignIn() async {
  if (kIsWeb) {
    final provider = OAuthProvider("apple.com")
      ..addScope('email')
      ..addScope('fullName');

    final userCredential = await FirebaseAuth.instance.signInWithPopup(provider);
    final firebaseUser = userCredential.user;
    final additionalInfo = userCredential.additionalUserInfo;

    // Web端从additionalUserInfo中获取用户姓名
    if (firebaseUser != null && firebaseUser.displayName == null && additionalInfo?.profile != null) {
      final givenName = additionalInfo!.profile!['given_name'] ?? '';
      final familyName = additionalInfo.profile!['family_name'] ?? '';
      final displayName = '$givenName $familyName'.trim();
      
      if (displayName.isNotEmpty) {
        try {
          await firebaseUser.updateDisplayName(displayName);
          await firebaseUser.reload();
        } catch (e) {
          debugPrint('更新Web端DisplayName失败: $e');
        }
      }
    }
    return userCredential;
  }

  // 移动端逻辑
  final rawNonce = generateNonce();
  final nonce = sha256ofString(rawNonce);

  final appleCredential = await SignInWithApple.getAppleIDCredential(
    scopes: [
      AppleIDAuthorizationScopes.email,
      AppleIDAuthorizationScopes.fullName,
    ],
    nonce: nonce,
  );

  final oauthCredential = OAuthProvider("apple.com").credential(
    idToken: appleCredential.identityToken,
    rawNonce: rawNonce,
  );

  final fixDisplayNameFromApple = [
    appleCredential.givenName ?? '',
    appleCredential.familyName ?? '',
  ].join(' ').trim();

  print(fixDisplayNameFromApple);

  final userCredential = await FirebaseAuth.instance.signInWithCredential(oauthCredential);
  final firebaseUser = userCredential.user;

  // 仅当用户displayName为空且获取到有效姓名时才更新
  if (firebaseUser != null && firebaseUser.displayName == null && fixDisplayNameFromApple.isNotEmpty) {
    try {
      await firebaseUser.updateDisplayName(fixDisplayNameFromApple);
      await firebaseUser.reload();
      // 重新获取用户对象确保本地数据更新
      final updatedUser = FirebaseAuth.instance.currentUser;
      print('更新后的DisplayName: ${updatedUser?.displayName}');
    } catch (e) {
      debugPrint('更新移动端DisplayName失败: $e');
    }
  }

  return userCredential;
}

Future<User?> signInWithApple(BuildContext context) =>
    signInOrCreateAccount(context, appleSignIn, 'APPLE');

关键修复点

  • 增加错误捕获:用try-catch包裹updateDisplayName操作,方便排查更新失败原因。
  • Web端逻辑补全:从additionalUserInfo.profile中提取姓名并更新,和移动端保持一致逻辑。
  • 条件校验增强:只有当fixDisplayNameFromApple不为空时才执行更新,避免空字符串覆盖。
  • 强制刷新用户数据:更新后重新获取currentUser,确保本地缓存的用户信息是最新的。

额外注意事项

  • 测试时请确保是首次授权Apple登录,后续登录Apple不会返回姓名信息,若要重新测试,需在Apple设置中取消对该应用的授权。
  • 如果需要在用户后续登录时更新姓名,需引导用户在应用内手动修改并调用updateDisplayName。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 05:35:17