AppPreflight Logo
AppPreflight
loading
返回指南

帐户删除要求:Apple 2024 年强制功能

AppPreflight 团队
2026-05-10
4 分钟阅读

帐户删除要求:Apple 2024 年强制功能

发布日期: 2026-05-10
最后更新: 2026-05-10
作者: AppPreflight 团队

概述

自 2024 年 9 月起,Apple 要求所有拥有用户帐户系统的应用在应用内实现帐户删除功能。这是不可谈判的,如果缺少将导致立即拒绝。本指南涵盖实现要求、最佳实践以及如何确保合规性。

为什么 Apple 要求帐户删除

监管要求

Apple 的帐户删除要求源自:

  1. GDPR(通用数据保护条例)

    • "被遗忘权" - 用户可以请求完全删除数据
    • 适用于所有拥有欧盟用户的应用
    • 违规罚款高达 €2000 万
  2. CCPA(加州消费者隐私法案)

    • 消费者有"删除权"
    • 适用于拥有加州用户的应用
    • 违规罚款高达每次违规 $7,500
  3. 其他数据保护法

    • 巴西:Lei Geral de Proteção de Dados(LGPD)
    • 中国:个人信息保护法(PIPL)
    • 印度:数字个人数据保护法(DPDPA)

Apple 的观点

Apple 在 App Store 审核指南 5.1.1 中声明:

"允许用户创建帐户的应用应提供用户从应用内删除其帐户的机制。"

这是强制性要求,而不是可选的。

帐户删除实现要求

UI/UX 要求

可访问性

  • 帐户删除选项在设置/个人资料中清楚可见
  • 位置:设置 > 帐户 > 删除帐户(标准)
  • 最多 3 次点击即可到达删除
  • 没有"隐藏"删除路径
  • 无需注销即可使用

用户确认

  • 显示说明后果的确认对话框
  • 需要明确确认(不仅仅是一次点击)
  • 清楚说明:"此操作无法撤销"
  • 显示将删除的数据
  • 考虑:需要密码确认以增加安全性

示例确认对话框:

"删除帐户"
"您确定要永久删除您的帐户吗?

这将:
✓ 删除您的个人资料和所有个人信息
✓ 删除所有保存的数据和首选项
✓ 取消任何活跃订阅
✓ 退款未使用的订阅时间

此操作无法撤销。

[取消] [删除帐户]"

服务器端要求

完全删除数据

  • 删除用户帐户记录
  • 删除所有关联用户数据
  • 删除个人资料信息
  • 删除活动历史记录
  • 删除首选项和设置
  • 删除保存的内容/文件
  • 删除身份验证令牌
  • 撤销刷新令牌
  • 从邮件列表中删除
  • 撤销 API 访问权限

不允许部分删除

❌ 不要保留:

  • "匿名化"用户数据
  • 历史数据(已删除用户信息)
  • 备份副本(包含识别信息)
  • 缓存数据存储
  • 链接到已删除用户的元数据

删除时间线

  • 请求时立即删除
  • 完全删除在 30 天内(推荐:即时)
  • 立即发送确认电子邮件
  • 没有重新激活选项(真正删除)

验证

删除后验证

测试删除后:

  1. 用户无法重新登录

    用已删除帐户登录 → 错误:"帐户未找到"
    
  2. API 调用失败,错误代码 401 或 404

    GET /api/user/profile → 401 Unauthorized
    
  3. 帐户数据不可恢复

    • 直接检查数据库
    • 检查备份系统
    • 帐户真正消失
  4. 订阅已取消

    • 如果用户有付费订阅,已取消
    • Apple 退款未使用时间
    • 用户可以重新订阅

实现清单

后端实现

删除 API 端点

// DELETE /api/auth/account
// 需要:身份验证令牌(JWT)
// 请求体:无
// 响应:
// { "success": true, "message": "Account deleted successfully" }

async deleteAccount(req, res) {
  const userId = req.user.id;

  try {
    // 1. 获取所有关联数据
    const user = await User.findById(userId);
    const userData = await getAllUserData(userId);

    // 2. 撤销所有令牌和会话
    await Session.deleteMany({ userId });
    await RefreshToken.deleteMany({ userId });

    // 3. 取消订阅
    if (user.subscriptionId) {
      await cancelSubscription(user.subscriptionId);
    }

    // 4. 删除关联数据
    await UserProfile.deleteMany({ userId });
    await UserFiles.deleteMany({ userId });
    await UserActivity.deleteMany({ userId });
    await UserPreferences.deleteMany({ userId });

    // 5. 删除用户帐户
    await User.deleteOne({ _id: userId });

    // 6. 发送确认电子邮件
    await sendDeletionConfirmationEmail(user.email);

    // 7. 记录删除以符合规定
    await AuditLog.create({
      action: 'ACCOUNT_DELETION',
      userId,
      timestamp: new Date()
    });

    res.json({ success: true });
  } catch (error) {
    res.status(500).json({ error: 'Deletion failed' });
  }
}

iOS 客户端实现

Swift 示例

import Alamofire
import JWTDecode

class AccountManager {
    static let shared = AccountManager()

    func deleteAccount(confirmation: Bool, completion: @escaping (Result<Void, Error>) -> Void) {
        guard confirmation else {
            completion(.failure(NSError(domain: "User did not confirm", code: -1)))
            return
        }

        guard let token = TokenManager.getAccessToken() else {
            completion(.failure(NSError(domain: "No auth token", code: -1)))
            return
        }

        let headers: HTTPHeaders = [
            "Authorization": "Bearer \(token)"
        ]

        AF.request(
            "https://api.app.com/auth/account",
            method: .delete,
            headers: headers
        )
        .validate()
        .response { response in
            switch response.result {
            case .success:
                // 清除本地数据
                UserDefaults.standard.removeObject(forKey: "accessToken")
                UserDefaults.standard.removeObject(forKey: "refreshToken")
                KeychainManager.clearAllData()

                // 导航到入门
                DispatchQueue.main.async {
                    NotificationCenter.default.post(
                        name: NSNotification.Name("AccountDeleted"),
                        object: nil
                    )
                    completion(.success(()))
                }

            case .failure(let error):
                completion(.failure(error))
            }
        }
    }
}

// 在 UI 中使用
class SettingsViewController: UIViewController {
    @IBAction func deleteAccountTapped(_ sender: UIButton) {
        showConfirmationDialog { confirmed in
            if confirmed {
                AccountManager.shared.deleteAccount(confirmation: true) { result in
                    switch result {
                    case .success:
                        self.showSuccessMessage("Account deleted")
                        self.navigationController?.popToRootViewController(animated: true)
                    case .failure(let error):
                        self.showErrorMessage(error.localizedDescription)
                    }
                }
            }
        }
    }
}

数据删除最佳实践

必须删除什么

个人可识别信息(PII)

  • 姓名
  • 电子邮件地址
  • 电话号码
  • 地址
  • 出生日期

帐户数据

  • 用户名和密码散列
  • 帐户首选项
  • 个人资料图片
  • 个人简介

用户活动

  • 登录历史记录
  • 操作历史记录
  • 搜索历史记录
  • 收藏夹/书签

用户生成的内容(UGC)

  • 如果用户可以单独删除,允许
  • 否则,将其与帐户匿名或删除

第三方集成

  • OAuth 令牌
  • API 凭证
  • 第三方服务关联
  • 日历邀请(日历应用)
  • 联系人参考(联系人应用)

合规性验证清单

提交到 App Store 之前:

  • 应用中存在帐户删除选项
  • 在 3 次点击内可访问
  • 需要明确确认
  • 清楚解释将删除什么
  • 实际删除用户帐户和数据
  • 删除后用户无法重新登录
  • 发送确认电子邮件
  • 允许使用相同电子邮件立即重新注册
  • 所有用户数据真正删除(数据库 + 备份)
  • 隐私政策已更新删除说明
  • 符合 GDPR、CCPA 和地区法律
  • 在多个设备上彻底测试

后续步骤

  1. 审核您当前应用的帐户删除功能
  2. 实现删除(不要延迟)
  3. 在真实设备上彻底测试
  4. 更新隐私政策以记录删除过程
  5. 验证生产数据库中的删除
  6. 使用 AppPreflight 预审工具 验证合规性
  7. 自信地提交到 App Store

帐户删除是强制性的,不是可选的。 立即实现以确保 App Store 批准和监管合规性。


这篇指南对你有帮助吗?