如何在Swift中使用.p8文件生成APNS授权令牌?
APNS设备间通信相关问题解决方案
一、Swift中基于.p8文件生成APNS授权令牌(无需依赖OpenSSL)
可以直接使用Apple原生的CryptoKit框架实现,完全不需要调用openssl命令行,避免跨平台依赖问题,适合多国部署的应用。以下是完整实现代码:
import CryptoKit import Foundation func generateAPNSToken(teamID: String, keyID: String, p8PrivateKeyData: Data) throws -> String { // 解析.p8格式的ECDSA私钥 guard let privateKey = try? P256.Signing.PrivateKey(pemRepresentation: String(decoding: p8PrivateKeyData, as: UTF8.self)) else { throw NSError(domain: "APNS", code: -1, userInfo: [NSLocalizedDescriptionKey: "加载P8私钥失败"]) } // 构造JWT Header let header = [ "alg": "ES256", "kid": keyID ] let headerData = try JSONSerialization.data(withJSONObject: header) let base64Header = base64URLEncode(data: headerData) // 构造JWT Payload(有效期1小时,符合APNS要求) let currentTime = Int(Date().timeIntervalSince1970) let payload = [ "iss": teamID, "iat": currentTime, "exp": currentTime + 3600 ] let payloadData = try JSONSerialization.data(withJSONObject: payload) let base64Payload = base64URLEncode(data: payloadData) // 生成签名输入串 let signingInput = "\(base64Header).\(base64Payload)" guard let signingInputData = signingInput.data(using: .utf8) else { throw NSError(domain: "APNS", code: -2, userInfo: [NSLocalizedDescriptionKey: "签名输入转换为数据失败"]) } // 生成ECDSA签名并编码 let signature = try privateKey.signature(for: signingInputData) let base64Signature = base64URLEncode(data: signature.rawRepresentation) // 组合成最终的JWT令牌 return "\(base64Header).\(base64Payload).\(base64Signature)" } // 辅助函数:实现JWT要求的Base64URL编码 private func base64URLEncode(data: Data) -> String { return data.base64EncodedString() .replacingOccurrences(of: "+", with: "-") .replacingOccurrences(of: "/", with: "_") .replacingOccurrences(of: "=", with: "") } // 使用示例 do { let teamID = "你的团队ID" let keyID = "你的P8密钥ID" guard let p8Path = Bundle.main.path(forResource: "AuthKey", ofType: "p8"), let p8Data = try? Data(contentsOf: URL(fileURLWithPath: p8Path)) else { fatalError("无法加载P8密钥文件") } let token = try generateAPNSToken(teamID: teamID, keyID: keyID, p8PrivateKeyData: p8Data) print("APNS授权令牌: \(token)") } catch { print("生成令牌失败: \(error.localizedDescription)") }
这段代码的核心是利用CryptoKit解析.p8私钥,生成符合APNS要求的JWT格式授权令牌,全程不依赖任何外部命令行工具。
二、通过AWS或Firebase实现设备间APNS通信
AWS方案
可以使用AWS Pinpoint服务实现:
- 客户端将APNS设备令牌注册到Pinpoint项目中
- 发送设备间消息时,调用Pinpoint的推送API,指定目标设备的令牌即可
- Pinpoint会自动处理APNS授权令牌的生成、签名和请求发送,无需自行维护相关逻辑
Firebase方案
Firebase Cloud Messaging (FCM)支持跨平台设备间通信,包括APNS:
- iOS客户端集成FCM SDK,将APNS设备令牌关联到Firebase实例ID
- 发送消息时,通过FCM API指定目标设备的Firebase实例ID,FCM会自动将消息转发到APNS
- FCM负责处理APNS的令牌管理、签名和推送流程,大幅简化开发工作
内容的提问来源于stack exchange,提问作者Michael Gaines
相关产品推荐
相关产品推荐

