• 2026年7月20日
  • 5 分钟阅读
  • SystemDo

消息推送系统安全怎么做?本地存储、通信与隐私权限

从服务端证书、本地 Token 存储、通信加密到客户端权限申请与日志脱敏,梳理消息推送系统在敏感数据保护与隐私合规上的工程实践。

消息推送系统安全怎么做?本地存储、通信与隐私权限
SystemDo
SystemDo

软件定制开发团队

"真正有价值的技术内容,应该能帮助客户更快判断方向、预算和落地路径。"

推送安全为何容易被低估

消息推送系统在项目中被视为“功能模块”,安全关注度远低于登录、支付或数据存储。这种低估源于一个常见误解:推送只是把一段文本从服务器发到手机,攻击面小。

实际上,推送系统是 APP 中少数几个需要同时处理服务端证书、客户端持久化 Token、设备标识符和用户隐私数据的模块。任何一个环节出现漏洞,都会导致敏感数据泄露、推送被劫持,甚至被用于大规模钓鱼攻击。

从工程角度看,推送系统安全涉及四个层面:服务端凭证管理、本地存储保护、通信加密与证书固定、客户端权限与隐私合规。下面逐一拆解。

服务端证书与密钥管理

推送凭证的存储风险

无论是 iOS 的 APNs(Apple Push Notification service)还是 Android 的 FCM(Firebase Cloud Messaging),服务端都需要持有长期有效的凭证。iOS 使用 .p8 密钥文件或 .p12 证书,Android 使用服务器密钥(Server Key)。这些凭证一旦泄露,攻击者可以直接向用户设备发送伪造推送。

常见的不安全做法包括:

  • 将凭证硬编码在应用配置文件中,上传到 Git 仓库。
  • 使用弱密码保护证书文件。
  • 在日志中打印密钥内容。

工程实践建议

凭证应存储在专用的密钥管理服务(KMS)或环境变量中,运行时动态读取。文件权限设置为仅服务进程可读。对于 .p8 密钥,建议使用托管密钥服务(如 AWS Secrets Manager、HashiCorp Vault)自动轮换。

证书过期是另一个容易被忽略的点。APNs 的 .p12 证书有效期为一年,到期后未更新会导致推送全部失败。建议在证书到期前 30 天设置监控告警,并提前准备新证书的签发流程。

多环境隔离

开发、测试和生产环境应使用不同的推送凭证。开发环境使用 Sandbox APNs,生产环境使用 Production APNs。混淆证书会导致开发阶段推送测试正常,但上线后失效,或者反过来。

本地 Token 与设备标识符存储

Token 是什么

推送 Token 是设备向推送服务注册后获得的唯一标识。服务端需要存储 Token 才能向特定设备推送。Token 本身不包含用户个人信息,但结合服务端业务数据(如用户 ID),可以关联到具体用户。

存储 Token 的风险在于:

  • 本地存储不当,其他应用或恶意进程可以读取。
  • Token 被窃取后,攻击者可以伪装设备接收本应发给用户的推送(例如验证码、通知)。

iOS 与 Android 的存储差异

iOS 使用 Keychain 存储推送 Token 是标准做法。Keychain 的数据在设备锁定时加密,且受硬件保护。部分开发者为图方便将 Token 存入 UserDefaults,这是不安全的。UserDefaults 数据以明文形式存储在应用沙盒中,备份到 iCloud 后更容易泄露。

Android 上,Token 通常由 FCM SDK 管理并回调给应用。应用需要将 Token 持久化以便后续发送。建议存储在 EncryptedSharedPreferences(AndroidX Security 库)中,而不是普通 SharedPreferences。EncryptedSharedPreferences 使用 AES-256 加密,密钥由 Android Keystore 保护。

服务端 Token 管理

服务端存储 Token 时应与用户 ID 绑定,但 Token 本身应视为敏感字段。数据库中的 Token 列建议加密存储,至少使用哈希加盐(不推荐,因为推送需要原文)。更实用的做法是使用对称加密(如 AES-256-GCM),密钥存储在 KMS 中。

Token 失效处理:设备卸载应用、重置推送服务或系统更新后,Token 会变更。服务端应定期清理无效 Token,避免向无效设备重复推送。建议每次推送后检查错误码,对 InvalidToken 或 Unregistered 状态码及时删除记录。

推送通道的通信加密

传输层保护

APNs 和 FCM 均强制要求 TLS 1.2 以上版本。服务端与推送网关之间的连接应使用证书验证,并启用证书固定(Certificate Pinning)。

证书固定的目的是防止中间人攻击:即使攻击者伪造了 CA 签发的证书,只要服务端只信任预置的证书指纹,连接仍然会被拒绝。对于 Java 服务端,可以通过自定义 TrustManager 实现;对于 Node.js,可以使用 tls.connect 的 ca 选项指定证书。

证书固定需要预留更新机制。证书更换时,如果客户端只固定了旧证书,服务端会无法连接。建议在代码中同时固定主证书和备用证书,或通过配置中心动态下发证书指纹。

推送内容加密

推送通知的 payload 在传输过程中是加密的(TLS),但到达设备后,系统会解密并显示在通知栏。如果推送内容包含敏感信息(如交易金额、验证码),建议在应用层额外加密。

做法是:服务端使用对称密钥加密 payload 中的敏感字段,客户端收到通知后,在应用内解密再显示。密钥可以通过其他安全通道(如登录接口)下发到客户端,存储在 Keychain 或 EncryptedSharedPreferences 中。

需要注意,推送通知的标题和正文在 iOS 和 Android 的通知栏中可能被其他应用或系统截获(例如通过 NotificationListenerService)。因此,即使应用层加密,也不应将高度敏感的数据直接放在推送通知中。更好的做法是推送一条“您有新的消息”,用户打开应用后再从服务端拉取实际内容。

客户端权限申请策略

推送权限的申请时机

iOS 和 Android 均要求用户授权才能接收推送通知。权限申请时机直接影响授权率。常见错误做法:

  • 应用启动后立即弹窗请求权限。
  • 拒绝后反复弹窗。

工程实践建议:

  • 首次启动后,先展示一个说明页面,解释推送的作用(如订单更新、活动通知),用户点击“开启通知”后再调用系统权限弹窗。
  • 如果用户拒绝,不要立即再次弹窗。可以在用户执行某个关键操作(如下单、支付)后,再次提示“开启通知可获取订单状态更新”,并提供手动跳转系统设置的入口。

Android 13+ 的通知权限

Android 13(API 33)开始,通知权限从自动授予改为运行时权限。应用需要在 AndroidManifest 中声明 POST_NOTIFICATIONS 权限,并在运行时请求。这与 iOS 的权限模型趋于一致。

适配时需要注意:

  • 如果应用最低版本低于 API 33,需要在运行时检查系统版本,只有 API 33 及以上才请求通知权限。
  • 请求权限时应使用 shouldShowRequestPermissionRationale 判断是否需要展示说明。

权限与隐私的平衡

推送权限本身不涉及敏感个人信息,但推送 Token 和设备标识符(如 IDFV、Android ID)的收集需要遵守隐私政策。在应用首次启动时,应在隐私协议中明确说明推送系统收集哪些数据、用于什么目的。

对于 GDPR 或中国《个人信息保护法》覆盖的用户,推送权限的申请应在用户同意隐私协议之后进行。如果用户拒绝隐私协议,不应发起权限请求,也不应调用推送 SDK 的注册方法。

日志与数据脱敏

推送日志中的敏感信息

开发调试时,日志中经常出现:

  • 推送 Token 原文
  • 用户 ID 和设备 ID
  • 推送 payload 中的业务数据(如订单号、金额)

这些日志如果落入第三方(如日志聚合服务、崩溃收集工具),可能构成数据泄露。

脱敏策略

在日志输出前,对敏感字段进行脱敏处理:

  • Token:仅输出前 4 位和后 4 位,中间用星号替代。
  • 用户 ID:输出哈希值(如 MD5 或 SHA-256 截断)。
  • payload:仅输出结构类型和字段数量,不输出具体值。

生产环境的日志级别应设置为 WARN 或 ERROR,避免将调试日志写入文件。日志文件应设置定期轮转和自动清理,保留周期建议不超过 30 天。

第三方 SDK 的日志控制

推送 SDK(如 Firebase、极光、个推)通常自带日志输出。集成时应在发布版本中关闭 SDK 的调试日志。以 Firebase 为例,可以通过 FirebaseMessaging.getInstance().setLogLevel(LogLevel.NONE) 关闭。对于无法通过 API 控制的 SDK,可以在 ProGuard 或 R8 规则中移除日志相关类。

隐私合规与审核

不同平台的审核要求

iOS 方面,App Store 审核会检查应用是否在推送内容中包含敏感数据,以及是否在未获得用户同意的情况下收集推送 Token。如果应用使用推送进行广告营销,必须在隐私协议中说明。

Android 方面,Google Play 对推送权限的申请时机有明确要求:应用不得在启动时立即请求通知权限,必须与功能关联。对于国内 Android 市场,部分应用商店(如华为、小米)要求推送服务必须在隐私协议同意后才能初始化。

合规清单

在项目上线前,建议逐项检查:

  • 隐私协议中是否明确列出推送系统收集的数据类型(Token、设备型号、系统版本)。
  • 是否在用户同意隐私协议后才调用推送 SDK 初始化。
  • 推送权限申请是否有前置说明页面。
  • 推送 payload 中是否包含未脱敏的个人信息。
  • 服务端是否存储了推送 Token 与用户 ID 的关联关系,以及是否加密存储。
  • 日志中是否包含 Token 或 payload 原文。

常见风险与应对

推送劫持与伪造

如果服务端推送凭证泄露,攻击者可以向所有 Token 发送伪造推送。应对措施:

  • 凭证定期轮换,最小权限原则(APNs 的 .p8 密钥可以限制只允许 push 操作)。
  • 服务端对推送请求来源进行 IP 白名单或 VPC 限制。
  • 推送内容中加入应用层签名,客户端验证签名后再显示。

Token 泄露后的影响范围

Token 泄露不等于用户数据泄露。但攻击者可以利用 Token 向用户发送钓鱼推送。应对措施:

  • 客户端在收到推送后,可以显示推送来源(如服务端名称),帮助用户识别伪造推送。
  • 对于高安全场景(如金融 APP),推送内容中应包含一个一次性验证码,用户需在应用内输入验证码才能查看详情。

第三方推送服务的选择

使用第三方推送服务(如极光、个推、腾讯移动推送)时,需要评估其安全能力:

  • 是否支持 TLS 1.2 以上连接。
  • 服务端是否提供证书固定选项。
  • 日志和监控数据是否脱敏。
  • 是否符合数据本地化要求(如 GDPR 要求数据存储在欧盟境内)。

SystemDo 在多个 APP 项目中集成过第三方推送服务,经验是:在选型阶段要求对方提供安全白皮书,并在合同中明确数据存储位置和泄露责任条款。对于金融、医疗等强监管行业,自建推送通道并配合应用层加密是更稳妥的选择。

总结要点

推送系统安全不是单一的技术实现,而是贯穿服务端凭证管理、本地存储、通信加密、权限申请和日志处理的全链路工程实践。关键判断:

  • 推送凭证必须使用 KMS 或环境变量管理,硬编码和 Git 提交是最高频的泄露途径。
  • Token 存储必须使用平台提供的加密存储方案(iOS Keychain、Android EncryptedSharedPreferences),不推荐 UserDefaults 或 SharedPreferences。
  • 推送内容中的敏感数据应在应用层加密,通知栏本身不是安全显示区域。
  • 权限申请应配合说明页面,避免首次启动立即弹窗,否则授权率会显著下降。
  • 日志脱敏是合规的底线,Token、用户 ID、payload 原文都不应出现在生产日志中。

这些实践适用于大部分 APP 项目,具体实现细节以各平台官方文档为准。