2017-04-26 96 views
2

首先,我已经检查这些问题,没有任何的运气:网页推送与VAPID:400/401未经授权注册

我想为我正在处理的Web应用程序实现Web推送通知。目前,我已经实现了以下目标:

  • 创建一个VAPID密钥对(with this guide)。
  • 注册服务人员(只有服务人员,我认为manifest.json不再需要)。
  • 订阅用户到服务器(订阅数据将存储在数据库中)。
  • 发送带有webpush宝石的推送通知。

设置后,一切工作正常(在本地和远程机器上)。但是,在几个小时之后(12到24小时之内),通知将停止在远程计算机上工作(本地主机完美工作)。

  • 铬:UnauthorizedRegistration 400(没有额外的信息),在此时间之后,从服务器端(Rails)的发送推送通知时,下面的错误抛出。
  • 火狐:{"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"}

后出现这个错误,我试图退订和重新订阅每个页面的访问用户。重新订阅完成后,数据库上的订阅字段会更新,但错误仍在抛出,具有相同的信息。浏览器和服务人员都不会抛出错误。

我试图通过在Chrome开发工具控制台上放置一些js代码,取消注册服务工作者并重置推送通知权限来手动强制重新签名,但没有任何方法可以解决此错误。我只能修复这个错误创建一个新的VAPID密钥对重新启动远程机器。在机器启动后,我又有12-24小时再次失败。另外,通知发送过程在导航服务器(nginx +独角兽),导轨控制台,也不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") 

回答

0

从24小时(默认)12小时更换过期时间后,现在正常工作:

Webpush.payload_send(
    message: "Hi!", 
    endpoint: "...", 
    p256dh: "...", 
    auth: "...", 
    vapid: { 
    subject: "...", 
    public_key: ENV['VAPID_PUBLIC_KEY'], 
    private_key: ENV['VAPID_PRIVATE_KEY'], 
    exp: 12.hours 
    } 
) 
0

它看起来像库发生了变化,这是我的固定它:

def send_push(payload, endpoint, p256dh, auth) 
    Webpush.payload_send(
    message: payload, 
    endpoint: endpoint, 
    p256dh: p256dh, 
    auth: auth, 
    vapid: { 
     public_key: '...', 
     private_key: '...', 
     expiration: 12 * 60 * 60 
    } 
) 
end 

请注意,密钥是expiration not exp,它是以秒为单位的到期时间。

相关问题