主域名网站调用子域Web Push订阅服务的可行方案咨询
可以实现,以下是具体技术方案与注意事项
核心逻辑
子域webpush.domain.com的Service Worker默认仅控制自身域内页面,但通过跨域消息通信(postMessage)或配置Service Worker作用域,可实现主域domain.com/www.domain.com调用子域的Web Push订阅服务。
具体实现步骤
1. 子域部署与配置
- 将PushPushGo/Gravitec要求的
service-worker.js放在webpush.domain.com根目录(如https://webpush.domain.com/service-worker.js)。 - 配置子域HTTP响应头,允许主域跨域访问:
Access-Control-Allow-Origin: https://domain.com, https://www.domain.com Access-Control-Allow-Methods: GET, POST, OPTIONS Access-Control-Allow-Headers: Content-Type - 在Service Worker中添加消息监听,处理主域的订阅请求:
self.addEventListener('message', (event) => { if (event.data.type === 'SUBSCRIBE') { self.registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: '你的VAPID公钥' }) .then(subscription => { event.source.postMessage({type: 'SUBSCRIBE_SUCCESS', data: subscription}); }) .catch(error => { event.source.postMessage({type: 'SUBSCRIBE_ERROR', error: error.message}); }); } });
2. 主域调用脚本实现
推荐用iframe桥接方案(兼容性更好),将脚本放在SaaS的专用子文件夹中:
// 主域脚本(如/js/webpush/subscribe.js) // 创建隐藏iframe作为跨域桥接 const iframe = document.createElement('iframe'); iframe.src = 'https://webpush.domain.com/bridge.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); // 触发订阅请求 function triggerWebPushSubscribe() { iframe.contentWindow.postMessage({type: 'REQUEST_SUBSCRIBE'}, 'https://webpush.domain.com'); } // 接收订阅结果 window.addEventListener('message', (event) => { if (event.origin !== 'https://webpush.domain.com') return; if (event.data.type === 'SUBSCRIBE_SUCCESS') { // 此处可将订阅信息同步到你的SaaS系统 console.log('订阅成功:', event.data.data); } else if (event.data.type === 'SUBSCRIBE_ERROR') { console.error('订阅失败:', event.data.error); } });
子域bridge.html的配套脚本:
// 注册子域的Service Worker navigator.serviceWorker.register('/service-worker.js') .then(registration => { window.addEventListener('message', (event) => { if (event.data.type === 'REQUEST_SUBSCRIBE') { // 转发订阅请求给Service Worker registration.active.postMessage({type: 'SUBSCRIBE'}); } }); });
3. 推送通知处理
订阅成功后,子域Service Worker负责接收推送并展示通知,可配置通知点击跳转主域:
// 子域Service Worker的推送监听 self.addEventListener('push', (event) => { const payload = event.data?.json() || {}; event.waitUntil( self.registration.showNotification(payload.title, { body: payload.body, data: { targetUrl: 'https://domain.com/notification-detail' } }) ); }); // 通知点击事件处理 self.addEventListener('notificationclick', (event) => { event.notification.close(); event.waitUntil(clients.openWindow(event.notification.data.targetUrl)); });
关键注意事项
- 强制HTTPS:主域与子域必须均为HTTPS环境(localhost开发环境除外),否则Service Worker与Web Push无法正常工作。
- 跨域消息验证:所有
postMessage通信必须校验event.origin,防止恶意请求。 - VAPID密钥一致性:确保PushPushGo/Gravitec提供的VAPID公钥在主域、子域脚本中统一配置。
- 浏览器兼容性:Chrome、Firefox、Edge等现代浏览器完全支持,Safari需额外配置APNs,需确认服务提供商是否支持。
内容的提问来源于stack exchange,提问作者friedman
相关产品推荐
相关产品推荐

