2017-02-21 30 views
9

Tôi đã phát triển dịch vụ thông báo đẩy cho trang web của mình. người lao động dịch vụ là:Thông báo đăng ký 'Đăng ký trái phép' hoặc 'Đã qua' hoặc 'Không được ủy quyền' trên web hết hạn

'use strict'; 
    self.addEventListener('push', function (event) {  
    var msg = {}; 
    if (event.data) { 
     msg = event.data.json(); 
    }  
    let notificationTitle = msg.title; 
    const notificationOptions = { 
     body: msg.body,//body 
     dir:'rtl',//direction 
     icon: msg.icon,//image 
     data: { 
      url: msg.url,//click 
     }, 
    }; 
    event.waitUntil(
     Promise.all([ 
     self.registration.showNotification(
      notificationTitle, notificationOptions),  
     ]) 
    ); 
    }); 
    self.addEventListener('notificationclick', function (event) {  
     event.notification.close(); 

    let clickResponsePromise = Promise.resolve(); 
    if (event.notification.data && event.notification.data.url) { 
     clickResponsePromise = clients.openWindow(event.notification.data.url); 
    } 
    const fetchOptions = 
     { method: 'post'}; 
    fetch('http://localhost:5333/usrh.ashx?click=true', fetchOptions). 
    then(function (response) 
    { 
     if (response.status >= 400 && response.status < 500) 
     {   
      throw new Error('Failed to send push message via web push protocol'); 
     } 
    }).catch((err) => 
    { 
     this.showErrorMessage('Ooops Unable to Send a Click', err); 
    }); 
}); 

self.addEventListener('notificationclose', function (event) { 
    const fetchOptions = 
     { method: 'post'}; 
    fetch('http://localhost:5333/usrh.ashx?close=true', fetchOptions). 
    then(function (response) 
    { 
     if (response.status >= 400 && response.status < 500) 
     {   
      throw new Error('Failed to send push message via web push protocol'); 
     } 
    }).catch((err) => 
    { 
     this.showErrorMessage('Ooops Unable to Send a Click', err); 
    }); 
}); 
self.addEventListener('pushsubscriptionchange', function() { 
    const fetchOptions = { 
     method: 'post' 
     , 
    }; 

    fetch('http://localhost:5333/usru.ashx', fetchOptions) 
     .then(function (response) { 
      if (response.status >= 400 && response.status < 500) { 
       console.log('Failed web push response: ', response, response.status); 
       throw new Error('Failed to update users.'); 
      } 
     }) 
     .catch((err) => { 
      this.showErrorMessage('Ooops Unable to Send a user', err); 
     }); 
}); 

Tôi đã đăng ký người sử dụng sử dụng thành công đoạn mã sau:

registerServiceWorker() { 
     if ('serviceWorker' in navigator) { 
      navigator.serviceWorker.register('http://localhost:5333/service-worker.js') 
       .catch((err) => { 
        this.showErrorMessage('Unable to Register SW', 'Sorry this demo requires a service worker to work and it ' + 'failed to install - sorry :('); 
        console.error(err); 
       }); 
     } else { 
      this.showErrorMessage('Service Worker Not Supported', 'Sorry this demo requires service worker support in your browser. ' + 
       'Please try this demo in Chrome or Firefox Nightly.'); 
     } 
    } 

class PushClient { 
    constructor(subscriptionUpdate, appkeys) { 
     this._subscriptionUpdate = subscriptionUpdate; 
     this._publicApplicationKey = appkeys; 
     if (!('serviceWorker' in navigator)) { 
      return; 
     } 
     if (!('PushManager' in window)) { 
      return; 
     } 
     if (!('showNotification' in ServiceWorkerRegistration.prototype)) { 
      return; 
     } 
     navigator.serviceWorker.ready.then(() => { 
      this.setUpPushPermission(); 
     }); 
    } 
    setUpPushPermission() { 
     return navigator.serviceWorker.ready.then((serviceWorkerRegistration) => { 
      return serviceWorkerRegistration.pushManager.getSubscription(); 
     }) 
      .then((subscription) => { 
       if (!subscription) { 
        return; 
       } 
       this._subscriptionUpdate(subscription); 
      }) 
      .catch((err) => { 
       console.log('setUpPushPermission() ', err); 
      }); 
    } 
    subscribeDevice() { 
     return new Promise((resolve, reject) => { 
      if (Notification.permission === 'denied') { 
       sc(3); 
       return reject(new Error('Push messages are blocked.')); 
      } 
      if (Notification.permission === 'granted') { 
       sc(3); 
       return resolve(); 
      } 
      if (Notification.permission === 'default') { 
       Notification.requestPermission((result) => { 
        if (result === 'denied') { 
         sc(0); 
        } else if (result === 'granted') { 
         sc(1); 
        } else { 
         sc(2); 
        } 
        if (result !== 'granted') { 
         reject(new Error('Bad permission result')); 
        } 
        resolve(); 
       }); 
      } 
     }) 
      .then(() => { 
       return navigator.serviceWorker.ready.then((serviceWorkerRegistration) => { 
        return serviceWorkerRegistration.pushManager.subscribe({ 
         userVisibleOnly: true 
         , applicationServerKey: this._publicApplicationKey.publicKey 
        , 
        }); 
       }) 
        .then((subscription) => { 
         this._subscriptionUpdate(subscription); 
         if (subscription) { 
          this.sendPushMessage(subscription); 
         } 
        }) 
        .catch((subscriptionErr) => { }); 
      }) 
      .catch(() => { }); 
    } 
    toBase64(arrayBuffer, start, end) { 
     start = start || 0; 
     end = end || arrayBuffer.byteLength; 
     const partialBuffer = new Uint8Array(arrayBuffer.slice(start, end)); 
     return btoa(String.fromCharCode.apply(null, partialBuffer)); 
    } 
    unsubscribeDevice() { 
     navigator.serviceWorker.ready.then((serviceWorkerRegistration) => { 
      return serviceWorkerRegistration.pushManager.getSubscription(); 
     }) 
      .then((pushSubscription) => { 
       if (!pushSubscription) { 
        this._subscriptionUpdate(null); 
        return; 
       } 
       return pushSubscription.unsubscribe() 
        .then(function (successful) { 
         if (!successful) { 
          console.error('We were unable to unregister from push'); 
         } 
        }); 
      }) 
      .then(() => { 
       this._subscriptionUpdate(null); 
      }) 
      .catch((err) => { 
       console.error('Error thrown while revoking push notifications. ' + 'Most likely because push was never registered', err); 
      }); 
    } 
    sendPushMessage(subscription) { 
     let payloadPromise = Promise.resolve(null); 
     payloadPromise = JSON.parse(JSON.stringify(subscription)); 
     const vapidPromise = EncryptionHelperFactory.createVapidAuthHeader(this._publicApplicationKey, subscription.endpoint, 'http://localhost:5333/'); 
     return Promise.all([payloadPromise, vapidPromise, ]) 
      .then((results) => { 
       const payload = results[0]; 
       const vapidHeaders = results[1]; 
       let infoFunction = this.getWebPushInfo; 
       infoFunction =() => { 
        return this.getWebPushInfo(subscription, payload, vapidHeaders); 
       }; 
       const requestInfo = infoFunction(); 
       this.sendRequestToProxyServer(requestInfo); 
      }); 
    } 
    getWebPushInfo(subscription, payload, vapidHeaders) { 
     let body = null; 
     const headers = {}; 
     headers.TTL = 60; 
     if (payload) { 
      headers.Encryption = `auth=${payload.keys.auth}`; 
      headers['Crypto-Key'] = `p256dh=${payload.keys.p256dh}`; 
      headers['Content-Encoding'] = 'aesgcm'; 
     } else { 
      headers['Content-Length'] = 0; 
     } 
     if (vapidHeaders) { 
      headers.Authorization = `WebPush ${vapidHeaders.authorization}`; 
      if (headers['Crypto-Key']) { 
       headers['Crypto-Key'] = `${headers['Crypto-Key']}; ` + `p256ecdsa=${vapidHeaders.p256ecdsa}`; 
      } else { 
       headers['Crypto-Key'] = `p256ecdsa=${vapidHeaders.p256ecdsa}`; 
      } 
     } 
     const response = { 
      headers: headers 
      , endpoint: subscription.endpoint 
     , 
     }; 
     if (body) { 
      response.body = body; 
     } 
     return response; 
    } 
    sendRequestToProxyServer(requestInfo) { 
     const fetchOptions = { 
      method: 'post' 
     , 
     }; 
     if (requestInfo.body && requestInfo.body instanceof ArrayBuffer) { 
      requestInfo.body = this.toBase64(requestInfo.body); 
      fetchOptions.body = requestInfo; 
     } 
     fetchOptions.body = JSON.stringify(requestInfo); 
     fetch('http://localhost:5333/usrh.ashx', fetchOptions) 
      .then(function (response) { 
       if (response.status >= 400 && response.status < 500) { 
        console.log('Failed web push response: ', response, response.status); 
        throw new Error('Failed to send push message via web push protocol'); 
       } 
      }) 
      .catch((err) => { 
       this.showErrorMessage('Ooops Unable to Send a Push', err); 
      }); 
    } 
} 

Tất cả các mã trong javascript. Tôi có thể nhận thành công thuê bao sử dụng infromarion trên máy chủ của tôi như:

Authorization: WebPush eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOiJodHRwcxxxxx 
Crypto-Key: p256dh=BBp90dwDWxxxxc1TfdBjFPqxxxxxwjO9fCip-K_Eebmg=; p256ecdsa=BDd3_hVL9fZi9Yboxxxxxxo 
endpoint: https://fcm.googleapis.com/fcm/send/cxxxxxxxxxxxxxxJRorOMHKLQ3gtT7 
Encryption: auth=9PzQZ1mut99qxxxxxxxxxxyw== 
Content-Encoding: aesgcm 

Ngoài ra tôi có thể thành công gửi một push to thành viên này sử dụng mã dưới đây trong C#:

public static async Task<bool> SendNotificationByte(string endpoint, string[] Keys, byte[] userSecret, byte[] data = null, 
             int ttl = 0, ushort padding = 0, bool randomisePadding = false, string auth="") 
     { 
      #region send 
      HttpRequestMessage Request = new HttpRequestMessage(HttpMethod.Post, endpoint);     
       Request.Headers.TryAddWithoutValidation("Authorization", auth); 
      Request.Headers.Add("TTL", ttl.ToString()); 
      if (data != null && Keys[1] != null && userSecret != null) 
      { 
       EncryptionResult Package = EncryptMessage(Decode(Keys[1]), userSecret, data, padding, randomisePadding); 
       Request.Content = new ByteArrayContent(Package.Payload); 
       Request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); 
       Request.Content.Headers.ContentLength = Package.Payload.Length; 
       Request.Content.Headers.ContentEncoding.Add("aesgcm"); 
       Request.Headers.Add("Crypto-Key", "dh=" + Encode(Package.PublicKey)+" ;"+Keys[2]+"="+Keys[3]); 
       Request.Headers.Add("Encryption", "salt=" + Encode(Package.Salt)); 
      } 
      using (HttpClient HC = new HttpClient()) 
      { 
       HttpResponseMessage res = await HC.SendAsync(Request).ConfigureAwait(false); 
       if (res.StatusCode == HttpStatusCode.Created) 
        return true; 
       else return false; 
      } 
      #endregion 
     } 

Vấn đề là sau một thời gian thời gian (khoảng 20 giờ hoặc thậm chí ít hơn), khi tôi muốn gửi một push to thành viên này tôi có các lỗi sau đây:

firefox thuê bao:

{StatusCode: 410, ReasonPhrase: 'Gone', Version: 1.1, Content: System.Net.Http.StreamContent, Headers: 
{ 
    Access-Control-Allow-Headers: content-encoding,encryption,crypto-key,ttl,encryption-key,content-type,authorization 
    Access-Control-Allow-Methods: POST 
    Access-Control-Allow-Origin: * 
    Access-Control-Expose-Headers: location,www-authenticate 
    Connection: keep-alive 
    Cache-Control: max-age=86400 
    Date: Tue, 21 Feb 2017 08:19:03 GMT 
    Server: nginx 
    Content-Length: 179 
    Content-Type: application/json 
}} 
0 thuê bao

chrome:

{StatusCode: 400, ReasonPhrase: 'UnauthorizedRegistration', Version: 1.1, Content: System.Net.Http.StreamContent, Headers: 
{ 
    X-Content-Type-Options: nosniff 
    X-Frame-Options: SAMEORIGIN 
    X-XSS-Protection: 1; mode=block 
    Alt-Svc: quic=":443"; ma=2592000; v="35,34" 
    Vary: Accept-Encoding 
    Transfer-Encoding: chunked 
    Accept-Ranges: none 
    Cache-Control: max-age=0, private 
    Date: Tue, 21 Feb 2017 08:18:35 GMT 
    Server: GSE 
    Content-Type: text/html; charset=UTF-8 
    Expires: Tue, 21 Feb 2017 08:18:35 GMT 
}} 

Tôi nghĩ rằng tôi đã bỏ lỡ điều gì đó, mà làm cho các thuê bao hết hạn, hoặc phải làm cho người dùng có thể đăng ký lại khi thông tin thuê bao của họ bị thay đổi hoặc hết hạn, nhưng tôi không biết làm thế nào ?! !

Trả lời

1

Sự cố được giải quyết bằng cách gửi thông báo đẩy đẩy tới người dùng đã đăng ký để đăng ký lại họ. Tôi đã viết một công việc mà tôi gửi một tiếng vang đẩy định kỳ và đăng ký lại người dùng và cập nhật thông tin của họ.

Để làm như vậy tôi gửi một thông điệp đặc biệt gọi là "đẩy echo" sử dụng mã dưới đây:

self.addEventListener('push', function (event) { 
lastEventName = 'push'; 
var msg = {}; 
if (event.data) { 
    msg = event.data.json(); 
    if (!!msg.isEcho) { 
     self.registration.pushManager.getSubscription() 
      .then(function (subscription) { 
       if (!subscription) { 
       } else { 
        subscription.unsubscribe().then(function() { 
         self.registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: base64UrlToUint8Array('xxxxxxxxxxxxxxxx') }) 
          .then(function (subscription) { 
           resubscription(subscription); 
          }); 
        }); 
        } 
      }); 
     return; 
    } 
} 
if (!!msg.isEcho) 
    return; 
let notificationTitle = msg.title; 
const notificationOptions = { 
    body: msg.body, 
    dir: 'rtl', 
    icon: msg.icon, 
    data: { 
     url: msg.url, 
     id: msg.id, 
     key: msg.key 
    }, 
}; 
event.waitUntil(
    Promise.all([ 
    self.registration.showNotification(
     notificationTitle, notificationOptions), 
    ]) 
); 

const fetchOptions = 
    { method: 'post', mode: 'no-cors' }; 
fetch('http://example.com', fetchOptions). 
    then(function (response) { 
     if (response.status >= 400 && response.status < 500) { 
      throw new Error('Failed to send push message via web push protocol'); 
     } 
     lastEventName = 'view'; 
    }).catch((err) => { 
     this.showErrorMessage('Ooops Unable to Send a Click', err); 
    }); 
}); 

Trong resubscription phương pháp bạn có thể unsubscribe và sau đó subscribe người sử dụng và cập nhật dữ liệu máy chủ.

1

Một số manh mối:

Cần phải đăng ký và kích hoạt sw tại thời điểm sự kiện đẩy đến. Điều này có nghĩa rằng bạn có thể không làm sạch phiên, sử dụng chế độ duyệt web riêng tư, làm sạch bộ nhớ cache của máy tính ở giữa.

Sự kiện đẩy phải đến từ cùng một nguồn gốc.

1

Tôi nghĩ vấn đề là về cách bạn gửi applicationServerKey. Tôi chỉ đã làm một ví dụ về những gì bạn muốn làm và tôi đã phải gửi rằng chìa khóa mã hóa với chức năng này:

function urlBase64ToUint8Array(base64String) { 
    const padding = '='.repeat((4 - base64String.length % 4) % 4); 
    const base64 = (base64String + padding) 
     .replace(/\-/g, '+') 
     .replace(/_/g, '/'); 

    const rawData = window.atob(base64); 
    const outputArray = new Uint8Array(rawData.length); 

    for (let i = 0; i < rawData.length; ++i) { 
     outputArray[i] = rawData.charCodeAt(i); 
    } 
    return outputArray; 
    } 

vì vậy bạn phải tạo đối tượng đăng ký của bạn theo cách này:

registration.pushManager 
    .subscribe({ 
     userVisibleOnly: true, 
     applicationServerKey: urlBase64ToUint8Array(this._publicApplicationKey.publicKey), 
    }) 

Chủ yếu những gì tôi đã làm là theo dõi this tutorial. Tôi có ví dụ làm việc đó trong this github repo. Tệp README bằng tiếng Tây Ban Nha, nhưng tôi nghĩ nó có thể giúp bạn.

+0

Tôi không nghĩ vậy! Nếu đây là giải pháp tôi không bao giờ có thể gửi thông báo đẩy. Như tôi đã đề cập, tôi có thể gửi cho người dùng khoảng 20 giờ! Sau đó có vẻ như đăng ký đã hết hạn! – Alex

+0

Tôi đã mã hóa các khóa của mình trước khi mã này được thực thi. – Alex

2

Tôi nghĩ rằng sự cố có thể được giải quyết bằng cách đăng ký lại người dùng.

Các vấn đề liên quan