Device Token:APNS令牌工作原理、获取与更新

作者: IT Sectr 发布日期: 2026-03-21 阅读时间: 11 分钟

Device Token是APNS分配给每个iOS设备的唯一标识符,用于路由推送通知。令牌在应用注册接收通知时由系统生成,必须发送到服务器,以便向该特定设备发送推送。根据Apple Developer Documentation, 2026Device Token可能在应用重装、从备份恢复设备或iOS更新时发生变化,因此服务器必须定期更新令牌以确保送达。

要点

  • 唯一性 — Device Token在特定APNS环境(sandbox/production)中对于每对“应用+设备”是唯一的。
  • 不持久性 — 令牌可能在应用重装、从备份恢复或iOS更新时发生变化,因此服务器需要更新机制。
  • 注册 — 应用通过UNUserNotificationCenter请求通知权限,随后系统在AppDelegate委托中返回Device Token。
  • APNS沙箱vs生产环境 — 开发使用带有独立证书的APNS沙箱环境;生产环境令牌不同,仅由生产环境APNS接受。
  • 令牌格式 — 32字节hex字符串,传输到服务器,在发送推送通知时用于apns-topic标头。

什么是Device Token

Device Token(设备令牌)是一个hex字符串形式的唯一标识符,由APNS(Apple推送通知服务)为iOS设备上的每个应用生成。令牌是服务器向特定设备发送推送通知的密钥。没有正确的Device Token,服务器无法送达推送 — APNS会返回400 BadRequest错误拒绝请求。

令牌如何生成

Device Token由iOS系统在应用安装后首次访问APNS时创建。生成过程包括对应用标识符(bundle ID)和设备唯一标识符(UID)的加密绑定,之后APNS返回32字节hex格式(64字符)的令牌。令牌不是永久的 — 系统在特定条件下可能生成新的令牌。

令牌在推送通知送达中的作用

当服务器发送推送通知时,它将Device Token包含在对APNS的HTTP/2请求中。APNS验证令牌的有效性:如果令牌属于不同环境(sandbox而非production)、已过期或被撤销,Apple服务器返回410 Gone或400 BadRequest错误。仅在令牌验证成功后,APNS才开始向设备送达通知。

Device Token与其他标识符的区别

Device Token不应与IDFA(广告标识符)、IDFV(供应商标识符)或UID(唯一设备标识符)混淆。IDFA和IDFV用于广告和分析,UID是硬件序列号。Device Token仅用于推送通知,不会在APNS之外泄露用户或设备信息。

标识符用途持久性
Device TokenAPNS推送通知路由可能变化
IDFA广告和追踪用户可重置
IDFV供应商标识(分析)同一开发者应用间持久
Bundle ID应用唯一标识符持久

设备如何获取和注册令牌

获取Device Token的过程包括几个必要步骤,从请求用户权限开始,到将令牌传输到服务器结束。每一步都至关重要 — 跳过任何一步都会导致无法向设备发送推送通知。

请求通知权限

第一步,应用通过UNUserNotificationCenter.current().requestAuthorization向用户请求发送通知的权限。用户可以选择同意、拒绝或选择可选选项(alert、badge、sound)。未经用户明确同意,即使应用调用registerForRemoteNotifications,系统也不会颁发Device Token。获得权限后,应用调用UIApplication.shared.registerForRemoteNotifications(),启动APNS注册过程。

从APNS获取令牌

注册后,APNS通过AppDelegate委托返回令牌:application(_:didRegisterForRemoteNotificationsWithDeviceToken:)。成功调用包含含有令牌的Data对象,需要将其转换为hex字符串以传输到服务器。如果出错,系统调用application(_:didFailToRegisterForRemoteNotificationsWithError:)并描述问题:证书配置错误、网络不可用或项目配置不正确。

将令牌传输到自己的服务器

获取令牌后,应用应立即将其传输到自己的服务器以保存在数据库中。API请求包括令牌、设备标识符(用于关联)、环境(sandbox/production)以及可选的附加数据:操作系统版本、设备型号、语言。建议在每次应用启动时重新传输令牌,以便服务器始终拥有最新的令牌。

swift
// 请求权限与APNS注册
func registerForPushNotifications() {
    UNUserNotificationCenter.current()
        .requestAuthorization(options: [.alert, .sound, .badge]) {
        [weak self] granted, error in
        guard granted else {
            print("未获得权限")
            return
        }
        DispatchQueue.main.async {
            UIApplication.shared
                .registerForRemoteNotifications()
        }
    }
}

// 从APNS获取Device Token
func application(
    _ application: UIApplication,
    didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
    let tokenString = deviceToken
        .map { String(format: "%02.2hhx", $0) }
        .joined()
    print("Device Token:\(tokenString)")

    // 发送令牌到服务器
    PushTokenService.shared
        .sendTokenToServer(tokenString) { success in
        if success {
            UserDefaults.standard.set(tokenString,
                forKey: "lastDeviceToken")
        }
    }
}

服务器端令牌管理

推送系统的服务器端应将Device Token存储在数据库中,与用户和环境关联。发送通知时,服务器构建对APNS的请求,将令牌包含在URL中,并使用JWT令牌(或证书)进行授权。正确的令牌管理对推送通知的送达率有重大影响。

令牌数据库结构

服务器上的令牌表至少应包含:Device Token(唯一)、用户标识符、环境(sandbox/production)、最后更新日期和状态(活跃/不活跃)。建议对令牌添加索引以便发送时快速查找,对用户添加索引以获取用户所有设备的列表。许多应用允许一个用户拥有多个设备 — 每个设备都有自己的令牌。

APNS请求授权

要发送推送通知,服务器必须通过两种方式授权对APNS的请求。基于证书的方式使用在Apple Developer Console中生成的SSL证书。基于令牌的方式使用带有.p8密钥的JWT(JSON Web令牌),有效期为30天,无需更新证书。基于令牌的授权被认为更现代,Apple推荐在新项目中使用。

构建APNS HTTP/2请求

对APNS的请求包括HTTP/2 POST方法、路径为/3/device/{device_token}的URL、授权标头和带有payload的JSON正文。apns-topic标头必须包含应用的bundle ID。apns-priority指定送达优先级(5 — 立即,10 — 省电模式)。apns-expiration设置从纪元开始的秒数时间,APNS将在此时间之前尝试送达通知。

js
// 通过APNS HTTP/2在Node.js上发送推送的示例
const http2 = require('http2');
const client = http2.connect('https://api.push.apple.com');

const deviceToken = 'abcdef0123456789...';
const payload = JSON.stringify({
    "aps": { "alert": "Hello!", "sound": "default" }
});

const req = client.request({
    ':method': 'POST',
    ':path': `/3/device/${deviceToken}`,
    'apns-topic': 'com.example.app',
    'apns-priority': '10',
    'apns-expiration': '0',
    'authorization': `bearer ${jwtToken}`
});
req.write(payload);
req.end();
req.on('响应', (headers) => {
    if (headers[':status'] === '200') {
        console.log('推送发送成功');
    }
});

批量发送和限流

向大量设备发送推送通知时,请使用带速度控制的批量发送。APNS建议每个连接每秒不超过1500个请求。超过限制时,Apple服务器返回429 Too Many Requests错误。对于大规模推送,请使用多个连接并均匀分配设备负载。

令牌更新与失效

Device Token不是永久的,在多种情况下可能发生变化,这要求服务器具备更新机制。如果服务器继续向过期的令牌发送推送,APNS返回410 Gone错误,指示该令牌在给定环境中不再有效。

令牌何时变化

Apple记录了Device Token变化的几种情况:用户重装应用、从iCloud备份恢复设备、安装新版iOS,以及重置网络或隐私设置。在每种情况下,应用在下次启动时会从APNS获取新令牌。服务器应更新数据库中的令牌,删除旧令牌并保存新令牌。

处理APNS的410 Gone错误

当服务器向过期的令牌发送推送时,APNS返回带有apns-unless-timestamp标头的HTTP 410。此标头指示令牌失效的时间。服务器应立即从数据库中删除或停用此令牌,以避免重复发送。忽略410错误会导致资源浪费和送达率降低。

定期清理不活跃的令牌

为保持令牌数据库的最新状态,建议运行定期清理。清理脚本分析最近N天的APNS日志,查找所有收到410错误的令牌,并在数据库中将其停用。此外,可以删除超过90天没有用户活动的令牌 — 这些是无用记录,只会增加数据库大小。

批量发送前验证令牌

在批量发送推送通知(新闻通讯、促销活动)之前,建议预先验证令牌的有效性。APNS不提供直接的批量令牌验证API,因此采用发送低优先级测试推送并分析错误的策略。返回410错误的令牌将从主发送中排除。

获取Device Token的代码示例

让我们来看Swift中获取Device Token的完整流程,包括错误处理和传输到服务器。代码涵盖请求权限、APNS注册、将Data转换为hex字符串、错误处理以及在失败时重试将令牌发送到自己的服务器。

swift
import UIKit
import UserNotifications

final class PushNotificationManager: NSObject {

    static let shared = PushNotificationManager()
    private let apiClient = APIClient()
    private var currentToken: String?

    func register() {
        UNUserNotificationCenter.current()
            .requestAuthorization(
                options: [.alert, .badge, .sound]) {
            [weak self] granted, error in
            guard granted else {
                Analytics.log(
                    "Push permission denied")
                return
            }
            DispatchQueue.main.async {
                UIApplication.shared
                    .registerForRemoteNotifications()
            }
        }
    }

    func handleDeviceToken(_ tokenData: Data) {
        let token = tokenData
            .map { String(format: "%02.2hhx", $0) }
            .joined()

        guard token != currentToken else { return }
        currentToken = token
        sendTokenToServer(token)
    }

    func handleRegistrationError(_ error: Error) {
        Analytics.log(
            "Push registration failed: \(error)")

        // 网络错误时延迟重试
        if let urlError = error as? URLError,
            urlError.code == .notConnectedToInternet {
            DispatchQueue.main.asyncAfter(
                deadline: .now() + 10) { [weak self] in
                self?.register()
            }
        }
    }

    private func sendTokenToServer(_ token: String) {
        let body = PushTokenRequest(
            token: token,
            environment: Environment.current == .debug
                ? "sandbox" : "production",
            osVersion: UIDevice.current.systemVersion,
            locale: Locale.current.identifier
        )
        apiClient.sendToken(body) { [weak self] result in
            if case .success = result {
                self?.currentToken = token
            }
        }
    }
}

注册时的错误处理

APNS注册错误可能由多种原因引起。最常见的原因包括:网络不可用、Xcode中证书配置错误(例如Push Notifications功能未启用)、使用模拟器(不支持推送)或配置文件不正确。在生产环境中,记录错误并在可能的情况下在下次应用启动时重试注册非常重要。

在模拟器上测试Device Token

iOS模拟器不支持获取真实的Device Token。要在模拟器上测试注册,请使用i386架构检查:在debug构建中可以模拟令牌获取或使用带有mock对象的UI测试。真实的推送通知测试始终在连接到Xcode的物理设备上执行。

常见问题

一个用户的Device Token会变化吗?

是的,Device Token可能在应用重装、从备份恢复设备或iOS更新时发生变化。服务器应处理令牌更新:从已知设备收到新令牌时替换旧令牌,收到410错误时从数据库中删除令牌。

Device Token的格式是什么?

Device Token是一个64字符的32字节hex字符串,小写(0–9, a–f)。示例:“a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2”。令牌作为Data从APNS传输,在应用端转换为字符串。

沙箱和生产环境令牌有什么区别?

沙箱令牌颁发给使用开发配置文件构建的应用,仅适用于api.sandbox.push.apple.com。生产环境令牌用于App Store和TestFlight,适用于api.push.apple.com。服务器应区分环境并将推送发送到相应的APNS端点。

如果服务器收到APNS的410错误怎么办?

410 Gone错误表示Device Token无效。服务器应立即从数据库中删除此令牌并停止尝试向其发送推送。响应中的apns-unless-timestamp标头指示令牌从何时起停止工作。

如何检查应用是否已获取Device Token?

检查AppDelegate中的委托方法application(_:didRegisterForRemoteNotificationsWithDeviceToken:)是否被调用。如果方法被调用 — 令牌已获取。使用调试日志或OSLog将令牌输出到Xcode控制台。在物理设备上,通过Network Link Conditioner检查令牌是否发送到服务器。

总结

  • Device Token — APNS中唯一的64字符hex设备标识符,用于推送通知的路由。
  • 获取令牌 — 过程包括请求用户权限、通过registerForRemoteNotifications在APNS注册以及在AppDelegate委托中处理。
  • 令牌不持久 — 可能在应用重装、从备份恢复或iOS更新时发生变化;服务器需要更新机制。
  • 沙箱vs生产环境 — 不同的APNS环境使用不同的令牌和端点;服务器在发送时应正确识别环境。
  • 服务器管理 — 令牌存储在数据库中,与用户、环境和状态关联;410 Gone错误表示令牌无效。
  • APNS授权 — 服务器使用JWT令牌或SSL证书对请求进行认证;Apple推荐新项目使用JWT。
  • Device Token — 推送基础设施的基本组件,每个通知的送达取决于其正确的获取和存储。

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读