2017-04-26 99 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,它是以秒爲單位的到期時間。

相關問題