首先,我已经检查过这些问题,但没有任何运气:
- Web Push API Chrome,返回“未经授权的注册” https://stackoverflow.com/questions/40801235/web-push-api-chrome-returning-unauthorized-registration
- [WebPush][VAPID] 请求失败,出现 400 UnauthorizedRegistration https://stackoverflow.com/questions/39336523/webpushvapid-request-fails-with-400-unauthorizedregistration
我正在尝试为我正在开发的网络应用程序实现网络推送通知。目前,我已经实现了以下目标:
- 创建 VAPID 密钥对(有了本指南 https://github.com/MartijnDwars/web-push/blob/master/doc/VAPID.md#generate-a-keypair).
- 注册一个 Service Worker (只有一个 Service Worker,我认为
manifest.json
不再需要)。
- 将用户订阅到服务器(订阅数据将存储在数据库中)。
- 发送推送通知webpush https://github.com/zaru/webpush gem.
设置完成后,一切正常(在本地主机和远程计算机上)。然而,几个小时后(12 到 24 小时之间),通知在远程计算机上停止工作(本地主机工作完美)。在此之后,从服务器端 (Rails) 发送推送通知时会引发以下错误:
-
Chrome:
UnauthorizedRegistration 400
(没有额外信息)。
-
Firefox:
{"code": 401, "errno": 109, "error": "Unauthorized", "more_info": "http://autopush.readthedocs.io/en/latest/http.html#error-codes", "message": "Request did not validate Invalid bearer token: Auth > 24 hours in the future"}
出现此错误后,我尝试在每次访问页面时取消订阅并重新订阅用户。重新订阅完成后,数据库上的订阅字段已更新,但仍然抛出错误,并具有相同的信息。浏览器和服务工作线程上都不会抛出任何错误。
I've tried to force the resubscription manually by placing some js code on the Chrome Dev Tools console, unregistering the service worker, and reseting the push notification permissions, but nothing solves the error. I can only fix this error by creating a new VAPID key pair rebooting the remote machine. After crebooting the machine, I've another 12-24 hours before it fails again. Also, the notifications send process don't work neither on rails server (nginx + unicorn), rails console, nor irb.
我不知道从现在起该去哪里。更糟糕的是,我每天只能尝试修复一次,因为它每 24 小时就会崩溃一次。我想我需要一些外部帮助来对问题有一个新的认识。我错过了什么吗? VAPID 使用并需要重新启动是否存在任何操作系统依赖性?
以下是一些可能有用的代码片段。很抱歉造成混乱,但我已经做了大量修改以尝试使其正常工作。
服务人员注册:
serviceWorkerRegistration = null
registerServiceWorker = ->
if 'serviceWorker' of navigator && 'PushManager' of window
navigator.serviceWorker.register("<js url>").then (reg) ->
serviceWorkerRegistration = reg
checkSubscription()
.catch (error) ->
console.warn 'Service Worker Error', error
else
console.warn 'Push messaging is not supported'
registerServiceWorker()
用户订阅和重新订阅
# Refresh user subscription (unsub + sub)
refreshUserSubscription = ->
unsubscribeUser(subscribeUser)
# Subscribe the user to the push server
subscribeUser = ->
return if !serviceWorkerRegistration
# Subscribe
serviceWorkerRegistration.pushManager.subscribe
userVisibleOnly: true
applicationServerKey: urlB64ToUint8Array('...')
.then (subscription) ->
pushSubscription subscription
.catch (err) ->
console.warn 'Failed to subscribe the user: ', err
# Unsubscribe user
unsubscribeUser = (callback)->
return unless serviceWorkerRegistration
serviceWorkerRegistration.pushManager.getSubscription().then (subscription) ->
if subscription
subscription.unsubscribe().then(callback)
else
callback()
.catch (error) ->
console.warn 'Error unsubscribing', error
# Push subscription to the web app
pushSubscription = (subscription) ->
data = if subscription then subscription.toJSON() else {}
$.post "<back-end endpoint>", subscription: data
# Fetch current subscription, and push it.
checkSubscription = () ->
serviceWorkerRegistration.pushManager.getSubscription()
.then (subscription) ->
pushSubscription(subscription)
# I think that this should be done with promises instead of a simple timeout.
setTimeout refreshUserSubscription, 1000
服务人员:
self.addEventListener 'push', (event) ->
title = "Example"
options = { body: "Example" }
notificationPromise = self.registration.showNotification(title, options)
event.waitUntil(notificationPromise)
网页推送调用:
webpush = WebPush.new({ endpoint: '...', keys: { p256dh: '...', auth: '...' } })
webpush.set_vapid_details(
"mailto:#{CONTACT_EMAIL}",
"<base64 public key>",
"<base64 private key>"
)
webpush.send_notification("foo")