webpush 基于浏览器的消息推送

前端 2024-05-30 351

Web Push 通知,是一种基于网络的推送通知技术,允许网站向用户发送通知,即使用户没有打开该网站。这种技术通常用于传递即时消息、新闻更新、促销活动、提醒等信息。Webpush 通知通过浏览器实现,支持多种桌面和移动设备上的现代浏览器,如 Chrome、Firefox、Safari 等。

使用,常见的编程语言都有支持webpush的基础库,详见:

https://github.com/web-push-libs

以下主要介绍使用流程和如何使用,以python的webpush库pywebpush演示,只给出核心代码

1.生成公钥,私钥

可以使用下面网址在线获取

https://web-push-codelab.glitch.me/

也可以使用webpush库生成,如nodejs webpush库支持通过命令行生成

  > web-push generate-vapid-keys --json
  > {"publicKey":"BGtkbcjrO12YMoDuq2sCQeHlu47uPx3SHTgFKZFYiBW8Qr0D9vgyZSZPdw6_4ZFEI9Snk1VEAj2qTYI1I1YxBXE","privateKey":"I0_d0vnesxbBSUmlDdOKibGo6vEXRO-Vu88QlSlm5j0"}

2.使用密钥

公钥一般放在前端,私钥放在后端代码中使用

前端代码:

service-worker.js

// Register event listener for the 'push' event.
self.addEventListener('push', function(event) {
  console.log('[Service Worker] 接收到推送通知:', event);
  const data = event.data.json();

  const title = data.title || '推送通知';
  const options = {
    body: data.body || '这是一条推送通知',
    icon: "", // 自定义图标
  };

  event.waitUntil(self.registration.showNotification(title, options));
});
self.addEventListener('notificationclick', function(event) {
  console.log('[Service Worker] 用户点击了通知');
  event.notification.close();
  //
  // event.waitUntil(
  //   clients.openWindow('https://example.com')
  // );
});

浏览器订阅,消息推送必须通过订阅才能推送

if ('serviceWorker' in navigator) {
	window.addEventListener('load', async () => {
		try {
			self.registration = await navigator.serviceWorker.register('/static/js/push/service-worker.js');
			console.log('服务工作线程注册成功:', this.registration);
		} catch (error) {
			self.$message.error("服务工作线程注册失败")
			console.error('服务工作线程注册失败:', error);
		}
	});
} else {
	self.$message.error("此浏览器不支持服务工作线程")
	console.warn('此浏览器不支持服务工作线程');
}
// 一般通过按钮点击触发后, 获取下面的订阅信息,注意endpoint, authKey, p256dhKey这些参数必须要保存
// 否则后端无法发生推送通知
async subscribeToPush() {
	const self = this
	try {
		console.log("123", window.Notification)
		const permission = await window.Notification.requestPermission();
		if (permission !== 'granted') {
			return self.$message.error("通知权限被拒绝")
		}
		if (self.subscription === null) {
			self.subscription = await this.registration.pushManager.subscribe({
				userVisibleOnly: true,
				applicationServerKey: '' // 替换为您的实际公钥
			});
		}
		// 提取订阅所需的终端、身份验证密钥和公钥
		const endpoint = self.subscription.endpoint;
		const authKey = self.subscription.getKey('auth');
		const p256dhKey = self.subscription.getKey('p256dh');
		const data = {
			browser: this.getBrowserName(),
			userAgent: navigator.userAgent,
			endpoint: endpoint,
			authKey: btoa(String.fromCharCode.apply(null, new Uint8Array(authKey))),
			p256dhKey: btoa(String.fromCharCode.apply(null, new Uint8Array(p256dhKey)))
		}
		console.log('订阅推送通知成功:', self.subscription);
	} catch (error) {
		console.error('订阅推送通知失败:', error);
	}
}

后端:

from pywebpush import webpush
# 如果使用edge浏览器,则endpoint 形如下:
# https://wns2-sg2p.notify.windows.com/w/?token=
# 其实消息推送可以理解为消息走了wns2-sg2p.notify.windows.com 推送到你电脑上的浏览器

data = json.dumps({
    'title': title,
    'body': content,
    # 'icon': 'https://example.com/icon.png'
})
webpush(
    ttl=3600,
    subscription_info={
        "endpoint": i.subscription.endpoint, # 浏览器端获取的endpoint
        "keys": {
            "p256dh": i.subscription.p256dh,
            "auth": i.subscription.auth
        }},
    data=data, # 推送消息
    vapid_private_key=settings.WEB_PUSH_PRIVATE_KEY, # 私钥
    vapid_claims={'sub': "mailto:xxxx@qq.com"}, # 自己的邮箱,确保使用一个有效的电子邮件地址,以便推送服务提供商在需要时能够联系到你。
    headers={'x-wns-cache-policy': 'no-cache'},  # 解决edge浏览器的推送
)

edge演示效果

如果浏览器关闭了消息通知权限,请开启,因为推送依赖于浏览器厂商,所以请不要使用chrome来推送消息,最好使用edge,火狐也可以(火狐的消息必须打开浏览器才能接收到,edge则不需要)

 

标签:前端

文章评论

评论列表

已有0条评论