当用户通过 PushManager.subscribe() 创建订阅时,给定
applicationServerKey
(VAPID 公钥),它会创建一个有效的订阅,可以将其内容发送并存储在数据库中。发送到数据库的内容看起来类似于以下内容:{"endpoint":"https://fcm.googleapis.com/fcm/send/dpH5lCsTSSM:APA91bHqjZxM0VImWWqDRN7U0a3AycjUf4O-byuxb_wJsKRaKvV_iKw56s16ekq6FUqoCF7k2nICUpd8fHPxVTgqLunFeVeB9lLCQZyohyAztTH8ZQL9WCxKpA6dvTG_TUIhQUFq_n",
"keys": {
"p256dh":"BLQELIDm-6b9Bl07YrEuXJ4BL_YBVQ0dvt9NQGGJxIQidJWHPNa9YrouvcQ9d7_MqzvGS9Alz60SZNCG3qfpk=",
"auth":"4vQK-SvRAN5eo-8ASlrwA=="
}
}
来源:推送通知入门
此对象提供唯一的端点,后端服务器知道在哪里调用以发送推送通知,并使用相应的VAPID私钥进行身份验证。
谷歌指出,此端点的唯一标识符是不透明的,无法确定任何个人数据。
该标识符是不透明的。作为开发者,您无法从中确定任何个人数据。此外,它也不稳定,因此无法用于跟踪用户。
按照Surya Sankar的教程,整个订阅对象可以发送到服务器并存储在数据库中,以便稍后发送推送通知到关联的浏览器/设备。但是,在记录条目进入数据库之前,会将其与已记录相同内容的条目进行比较,以避免创建重复项。
@app.route("/api/push-subscriptions", methods=["POST"])
def create_push_subscription():
json_data = request.get_json()
subscription = PushSubscription.query.filter_by(
subscription_json=json_data['subscription_json']
).first()
if subscription is None:
subscription = PushSubscription(
subscription_json=json_data['subscription_json']
)
db.session.add(subscription)
db.session.commit()
return jsonify({
"status": "success"
})
因为整个订阅对象与webpush
一起使用来触发推送通知,所以我理解整个订阅对象需要发送到服务器。
from pywebpush import webpush, WebPushException
import json
from flask import current_app
def trigger_push_notification(push_subscription, title, body):
try:
response = webpush(
# Uses entire subscription object stored in database as parameter
subscription_info=json.loads(push_subscription.subscription_json),
data=json.dumps({"title": title, "body": body}),
vapid_private_key=current_app.config["VAPID_PRIVATE_KEY"],
vapid_claims={
"sub": "mailto:{}".format(
current_app.config["VAPID_CLAIM_EMAIL"])
}
)
return response.ok
except WebPushException as ex:
if ex.response and ex.response.json():
extra = ex.response.json()
print("Remote service replied with a {}:{}, {}",
extra.code,
extra.errno,
extra.message
)
return False
def trigger_push_notifications_for_subscriptions(subscriptions, title, body):
return [trigger_push_notification(subscription, title, body)
for subscription in subscriptions]
这遵循了该库的文档(pywebpush)中的指南,该文档规定在其自述文件的Usage部分中执行以下操作。
有了这个,我对订阅对象的哪些部分包含敏感信息(即"auth"
)感到好奇? PushSubscription.getKey()
的文档说明"auth"
是认证密钥,"p256dh"
是公钥。鉴于推送通知只能通过 HTTPS 使用,客户端和服务器之间的通信将是安全的。
当尝试从前端引用此订阅时,我可以使用订阅对象的哪个部分作为标识符引用数据库中的此条目?
(即,该端点的GET
请求如下所示:https:/example.com/client/push-subscription/<subscription-object-identifier>
)
我认为不能使用整个订阅对象作为此端点的标识符,因为它会暴露"auth"
下的内容。 我可以使用"endpoint"
或"p256dh"
下的内容作为标识符吗?因为它们是唯一的并且不会暴露任何敏感数据。