بروتوكول Web Push

لقد رأينا كيف يمكن استخدام مكتبة لتشغيل رسائل الدفع، ولكن ما الذي ما تفعله هذه المكتبات بالضبط؟

حسنًا، إنهم يرسلون طلبات الشبكة مع التأكد من أن هذه الطلبات بالتنسيق الصحيح. المواصفة التي تحدد طلب الشبكة هذا هي بروتوكول Web Push

مخطّط بياني لإرسال رسالة فورية من الخادم إلى دفعة
الخدمة

يوضح هذا القسم كيف يمكن للخادم التعرّف على نفسه باستخدام التطبيق المفاتيح وكيفية إرسال حمولة البيانات المشفرة والبيانات المرتبطة بها.

هذا ليس جانبًا رائعًا لدفع الويب ولست خبيرة في التشفير، ولكن دعونا نلقي نظرة على كل قطعة لأنّها مفيدة لمعرفة ما تفعله هذه المكتبات خفية.

مفاتيح خادم التطبيقات

عندما نشترك مستخدمًا، نمرر applicationServerKey. هذا المفتاح هو إلى خدمة الإرسال واستخدمته للتحقق من أن التطبيق الذي اشترك فإن المستخدم هو أيضًا التطبيق الذي يؤدي إلى إرسال رسائل الدفع.

عندما نقوم بتشغيل رسالة فورية، تكون هناك مجموعة من العناوين التي نرسلها السماح لخدمة الدفع بمصادقة التطبيق. (يتم تحديد هذا بمواصفات VAPID).

ماذا يعني كل هذا في الواقع وماذا يحدث بالضبط؟ حسنًا هذه هي الخطوات المتخذة مصادقة خادم التطبيقات:

  1. ويوقِّع خادم التطبيق بعض معلومات JSON باستخدام مفتاح التطبيق الخاص الخاص به.
  2. يتم إرسال هذه المعلومات الموقَّعة إلى خدمة الإرسال كعنوان في طلب POST.
  3. تستخدم خدمة الإرسال المفتاح العام الذي تم تخزينه منه. "pushManager.subscribe()" للتحقّق من المعلومات المُستلَمة، تم التوقيع من قِبل المفتاح الخاص المرتبط بالمفتاح العام. تذكير: المفتاح العام هو تم تمرير applicationServerKey إلى مكالمة الاشتراك.
  4. إذا كانت المعلومات الموقَّعة صالحة، ترسل خدمة الإرسال الطلب. رسالة إلى المستخدم.

فيما يلي مثال على تدفق المعلومات هذا. (لاحظ وسيلة الإيضاح في أسفل اليسار للإشارة إلى المفاتيح العامة والخاصة).

رسم توضيحي لكيفية استخدام مفتاح خادم التطبيق الخاص عند إرسال
رسالة

تعمل "المعلومات الموقعة" الذي تتم إضافته إلى عنوان في الطلب هو رمز JSON المميّز للويب.

الرمز المميّز للويب بتنسيق JSON

رمز JSON المميّز للويب (أو JWT اختصارًا) هو طريقة أو إرسال رسالة إلى جهة خارجية ليتمكّن المستلِم من التأكّد من صحتها الذي أرسلها.

عندما تتلقّى جهة خارجية رسالة، عليها وصول المُرسِلين إليها. المفتاح العام واستخدامه للتحقق من صحة توقيع JWT. إذا كانت التوقيع صالح، فلا بد أن يكون قد تم توقيع JWT باستخدام النتائج مفتاح خاص لذا يجب أن يكون من المرسل المتوقع.

هناك مجموعة من المكتبات على https://jwt.io/ توقيع البرنامج نيابةً عنك، وأنصحك بتنفيذه حيث يمكن. لتحقيق الاكتمال، دعنا نلقي نظرة على كيفية إنشاء JWT موقَّع يدويًا.

إرسال الويب بلغة البرمجة JWT الموقّعة

رمز JWT الموقّع هو مجرد سلسلة، على الرغم من أنه يمكن اعتباره ثلاث سلاسل تم ضمها بالنقاط.

صورة توضيحية للسلاسل في ملف JSON على الويب
رمز مميز

السلسلتان الأولى والثانية (معلومات JWT وبيانات JWT) عبارة عن أجزاء من تشير هذه السمة إلى أنّ تنسيق JSON يكون بترميز base64، ما يعني أنّه سهل القراءة للجميع.

السلسلة الأولى هي معلومات عن JWT نفسه، مما يشير إلى الخوارزمية التي استُخدم لإنشاء التوقيع.

يجب أن تحتوي معلومات JWT للدفع على الويب على المعلومات التالية:

{
  "typ": "JWT",
  "alg": "ES256"
}

السلسلة الثانية هي بيانات JWT. يقدم هذا معلومات عن مُرسِل JWT، الذي المرادفة له ومدة صلاحيته.

لإرسال الويب، ستكون البيانات بالتنسيق التالي:

{
  "aud": "https://some-push-service.org",
  "exp": "1469618703",
  "sub": "mailto:example@web-push-book.org"
}

قيمة aud هي "الجمهور"، أي المستخدم هو JWT. بالنسبة إلى الويب، اضغط على الجمهور هو خدمة الدفع، لذا قمنا بتعيينها على مصدر الدفع الخدمة.

تشير قيمة exp إلى انتهاء صلاحية JWT، ما يمنع المتطفلين من التطفل قادرة على إعادة استخدام JWT في حالة اعتراضها. انتهاء الصلاحية هو طابع زمني في ثانية ويجب ألا تزيد عن 24 ساعة.

في Node.js، يتم ضبط تاريخ انتهاء الصلاحية باستخدام:

Math.floor(Date.now() / 1000) + 12 * 60 * 60;

فمن 12 ساعة بدلاً من 24 ساعة لتجنب أي مشكلات تتعلق بالاختلافات في الساعة بين تطبيق الإرسال وخدمة الإرسال.

أخيرًا، يجب أن تكون قيمة sub عنوان URL أو عنوان بريد إلكتروني mailto. وذلك حتى إذا احتاجت خدمة الدفع للوصول إلى المرسل، يمكنها العثور على معلومات الاتصال من JWT. (لهذا السبب احتاجت مكتبة Web-push إلى عنوان بريدك الإلكتروني).

وتمامًا مثل معلومات JWT، يتم تشفير بيانات JWT كبيانات base64 آمنة لعنوان URL. السلسلة.

السلسلة الثالثة، التوقيع، هي نتيجة أخذ أول سلسلتين. (معلومات JWT وبيانات JWT)، مع ربطها بحرف نقطة، واستدعاء "الرمز المميز غير الموقَّع"، وتوقيعه.

تتطلب عملية التوقيع تشفير "الرمز المميّز غير الموقَّع" باستخدام ES256. وفقًا لـ JWT المواصفات، يشير الاختصار ES256 إلى عبارة "ECDSA باستخدام المنحنى P-256 خوارزمية التجزئة SHA-256". باستخدام تشفير الويب، يمكنك إنشاء التوقيع كما يلي:

// Utility function for UTF-8 encoding a string to an ArrayBuffer.
const utf8Encoder = new TextEncoder('utf-8');

// The unsigned token is the concatenation of the URL-safe base64 encoded
// header and body.
const unsignedToken = .....;

// Sign the |unsignedToken| using ES256 (SHA-256 over ECDSA).
const key = {
  kty: 'EC',
  crv: 'P-256',
  x: window.uint8ArrayToBase64Url(
    applicationServerKeys.publicKey.subarray(1, 33)),
  y: window.uint8ArrayToBase64Url(
    applicationServerKeys.publicKey.subarray(33, 65)),
  d: window.uint8ArrayToBase64Url(applicationServerKeys.privateKey),
};

// Sign the |unsignedToken| with the server's private key to generate
// the signature.
return crypto.subtle.importKey('jwk', key, {
  name: 'ECDSA', namedCurve: 'P-256',
}, true, ['sign'])
.then((key) => {
  return crypto.subtle.sign({
    name: 'ECDSA',
    hash: {
      name: 'SHA-256',
    },
  }, key, utf8Encoder.encode(unsignedToken));
})
.then((signature) => {
  console.log('Signature: ', signature);
});

يمكن لخدمة الإرسال التحقق من صحة JWT باستخدام مفتاح خادم التطبيقات العامة فك تشفير التوقيع والتأكّد من أنّ السلسلة التي تم فك تشفيرها هي نفسها باعتباره "الرمز المميز غير الموقَّع" (أي أول سلسلتين في JWT).

يتم إرسال ملف JWT الموقّع (أي السلاسل الثلاث التي تضم نقاطًا) إلى الويب. إرسال خدمة مثل العنوان Authorization مع إضافة WebPush، كما يلي:

Authorization: 'WebPush [JWT Info].[JWT Data].[Signature]';

ينص بروتوكول Web Push أيضًا على أن مفتاح خادم التطبيق العام يجب أن يكون ويتم إرسالها في العنوان Crypto-Key كسلسلة بيانات مشفّرة لـ base64 آمنة على عنوان URL مع تمت إضافة p256ecdsa= في البداية.

Crypto-Key: p256ecdsa=[URL Safe Base64 Public Application Server Key]

تشفير الحمولة

دعونا نلقي نظرة بعد ذلك على كيفية إرسال حمولة بيانات مع رسالة فورية بحيث عندما يكون تطبيق الويب يتلقى رسالة فورية، فيمكنه الوصول إلى البيانات التي يتلقاها.

وهناك سؤال شائع يطرحه أي شخص استخدم خدمات دفع أخرى، وهو لماذا يدفع الويب أن يتم تشفير حمولة البيانات؟ باستخدام التطبيقات الأصلية، يمكن للرسائل الفورية إرسال البيانات كنص عادي.

وأحد عناصر جمال الويب هو أنه نظرًا لأن جميع خدمات الدفع هذه تستخدم نفس واجهة برمجة التطبيقات (بروتوكول الدفع على الويب)، فلا يحتاج المطورون إلى الاهتمام بمن خدمة الدفع. يمكننا تقديم طلب بالتنسيق الصحيح ونتوقع إرسال الرسالة الفورية. والجانب السلبي لهذا الأسلوب هو أنّ المطوّرين يمكنهم إرسال رسائل إلى خدمة إرسال رسائل غير موثوق بها. من تشفير الحمولة، لا يمكن لخدمة الدفع قراءة البيانات المرسلة. ولا يمكن لأحد سوى المتصفّح فك تشفير المعلومات. يحمي هذا هوية المستخدم البيانات.

يتم تحديد تشفير الحمولة في قسم تشفير الرسائل المواصفات.

قبل أن نلقي نظرة على الخطوات المحددة لتشفير حمولة رسائل الدفع، يجب أن نتناول بعض الأساليب التي سيتم استخدامها أثناء عملية التشفير الدفع. (نصيحة قبعة كبيرة لشركة Mat Scales لمقالته المتميزة حول الدفع encryption.)

ECDH وHKDF

ويتم استخدام كل من ECDH وHKDF خلال عملية التشفير ويقدمان فوائد الغرض من تشفير المعلومات.

ECDH: تبادل مفتاح Diffie-Hellman مع المنحنى الإهليلجي

تخيل أنّ لديك شخصين يريدان مشاركة المعلومات، وهما نبيلة وهبة. لدى نبيلة وسامر مفاتيحهما العامة والخاصة. نبيلة ويوسف مشاركة مفاتيحهما العامة مع بعضها البعض.

الخاصية المفيدة للمفاتيح التي تم إنشاؤها باستخدام ECDH هي أن نبيلة يمكنها استخدامها الخاص والمفتاح العام لكامل لإنشاء قيمة سرية 'X'. يستطيع يوسف إجراء ذلك الشيء ذاته، حيث أخذ مفتاحه الخاص ومفتاح أليس العام تنشئ نفس القيمة 'X' بشكل مستقل. هذا يجعل "X" سر مشترك ولم يكن على نبيلة وبوب سوى مشاركة مفتاحهما العام. دِلْوَقْتِي بوب وأليس يمكن استخدام "X" لتشفير وفك تشفير الرسائل بينهما.

على حد علمي، تحدد ECDH خصائص المنحنيات التي تسمح بهذه "الميزة". عمل سر مشترك "X".

في ما يلي شرح عام عن ECDH، وإذا أردت الحصول على المزيد من المعلومات، ننصحك بمشاهدة هذا الفيديو.

في ما يتعلق بالرموز البرمجية؛ تأتي معظم اللغات / المنصات مزودة بمكتبات لجعلها ويسهل إنشاء هذه المفاتيح.

في العقدة، نفعل ما يلي:

const keyCurve = crypto.createECDH('prime256v1');
keyCurve.generateKeys();

const publicKey = keyCurve.getPublicKey();
const privateKey = keyCurve.getPrivateKey();

HKDF: دالة اشتقاق المفاتيح المستندة إلى HMAC

تحتوي ويكيبيديا على وصف موجز عن HKDF:

HKDF هي دالة اشتقاق مفاتيح تستند إلى HMAC تحول أي مفتاح ضعيف إلى مادة رئيسية قوية من الناحية المشفرة. يمكن استخدامها، على سبيل المثال، لتحويل ديفي هيلمان إلى مواد رئيسية تبادلت الأسرار مناسبة للاستخدام في التشفير أو التحقق من السلامة أو المصادقة.

وبشكل أساسي، ستأخذ منطقة HKDF مدخلات غير آمنة بشكل خاص وتجعلها أكثر أمانًا.

تتطلب المواصفات التي تحدد هذا التشفير استخدام خوارزمية SHA-256 كخوارزمية التجزئة ويجب ألا يزيد طول المفاتيح الناتجة لـ HKDF في الدفع على الويب عن 256 بت (32 بايت).

في العقدة، يمكن تنفيذ هذا على النحو التالي:

// Simplified HKDF, returning keys up to 32 bytes long
function hkdf(salt, ikm, info, length) {
  // Extract
  const keyHmac = crypto.createHmac('sha256', salt);
  keyHmac.update(ikm);
  const key = keyHmac.digest();

  // Expand
  const infoHmac = crypto.createHmac('sha256', key);
  infoHmac.update(info);

  // A one byte long buffer containing only 0x01
  const ONE_BUFFER = new Buffer(1).fill(1);
  infoHmac.update(ONE_BUFFER);

  return infoHmac.digest().slice(0, length);
}

أضِف نصيحة إلى مقالة مقياس Mats حول نموذج الرمز هذا.

يغطي هذا الجزء بإحكام ECDH وHKDF.

تقنية ECDH هي طريقة آمنة لمشاركة المفاتيح العامة وإنشاء مفتاح سرّي مشترك. إن HKDF هي وسيلة لأخذ غير آمنة وجعلها آمنة.

سيتم استخدام ذلك أثناء تشفير الحمولة لدينا. بعد ذلك، دعونا نلقي نظرة على ما نأخذه في المدخلات وكيف يتم تشفيرها.

مدخلات

عندما نريد إرسال رسالة فورية إلى مستخدم لديه حمولة، هناك ثلاثة إدخالات نحتاجها:

  1. الحمولة نفسها.
  2. سر auth من PushSubscription.
  3. المفتاح p256dh من PushSubscription.

لاحظنا أنّه يتم استرداد القيمتين auth وp256dh من PushSubscription، إلا أنّ ذلك قد يكون تذكير سريع: نظرًا إلى الاشتراك، سنحتاج إلى القيم التالية:

subscription.toJSON().keys.auth;
subscription.toJSON().keys.p256dh;

subscription.getKey('auth');
subscription.getKey('p256dh');

يجب التعامل مع قيمة auth كقيمة سرية وألا تتم مشاركتها خارج التطبيق.

المفتاح p256dh هو مفتاح عام، ويُشار إليه أحيانًا باسم المفتاح العام للعميل. هنا سنشير إلى p256dh على أنّه المفتاح العام للاشتراك. يتم إنشاء المفتاح العام للاشتراك بواسطة المتصفح. سيحتفظ المتصفح بسرية المفتاح الخاص ويستخدمه لفك تشفير حمولة البيانات.

هذه القيم الثلاث، auth وp256dh وpayload مطلوبة كمدخلات ونتيجة عملية التشفير هي الحمولة المشفرة والقيمة العشوائية ومفتاح عام يُستخدم فقط تشفير البيانات.

الملح

يجب أن تبلغ القيمة العشوائية للبيانات 16 بايت. في NodeJS، سنفعل ما يلي لإنشاء قيمة عشوائية:

const salt = crypto.randomBytes(16);

المفاتيح العامة / الخاصة

يجب إنشاء المفاتيح العامة والخاصة باستخدام منحنى القطع البيضاوي P-256، وهو ما سنفعله في Node على النحو التالي:

const localKeysCurve = crypto.createECDH('prime256v1');
localKeysCurve.generateKeys();

const localPublicKey = localKeysCurve.getPublicKey();
const localPrivateKey = localKeysCurve.getPrivateKey();

سنشير إلى هذه المفاتيح باسم "المفاتيح المحلية". تُستخدم فقط للتشفير ولها لا شيء له علاقة بمفاتيح خادم التطبيقات.

باستخدام البيانات الأساسية وسر المصادقة والمفتاح العام للاشتراك كمدخلات ومع مفتاح تم إنشاؤه حديثًا مجموعة من المفاتيح المحلية، فإنّنا مستعدون لإجراء بعض التشفير.

المفتاح السرّي المشترك

تتمثل الخطوة الأولى في إنشاء مفتاح سري مشترك باستخدام المفتاح العام للاشتراك المفتاح الخاص (هل تتذكر شرح ECDH مع علياء وبوب؟ تمامًا).

const sharedSecret = localKeysCurve.computeSecret(
  subscription.keys.p256dh,
  'base64',
);

يستخدم هذا في الخطوة التالية لحساب المفتاح العشوائي الزائف (PRK).

مفتاح عشوائي زائف

المفتاح العشوائي الزائف (PRK) هو تركيبة من مصادقة اشتراك Push والسر المشترك الذي أنشأناه للتو.

const authEncBuff = new Buffer('Content-Encoding: auth\0', 'utf8');
const prk = hkdf(subscription.keys.auth, sharedSecret, authEncBuff, 32);

قد تتساءل عن الغرض من السلسلة Content-Encoding: auth\0. باختصار، ليس لها هدف واضح، على الرغم من أنّ المتصفّحات فك تشفير رسالة واردة والبحث عن ترميز المحتوى المتوقع. يضيف \0 بايت بقيمة 0 إلى نهاية المخزن المؤقت. هذا هو متوقع من المتصفحات فك تشفير الرسالة التي تتوقع العديد من وحدات البايت لتشفير المحتوى، متبوعة ببايت بقيمة 0، متبوعة بشكل أفضل.

يعمل المفتاح الزائف العشوائي على تشغيل المصادقة والمفتاح السري المشترك وجزء من معلومات الترميز. من خلال HKDF (أي تعزيز قوة التشفير).

السياق

"السياق" هو مجموعة من وحدات البايت التي تُستخدم لحساب قيمتين لاحقًا في التشفير المتصفح. إنها في الأساس عبارة عن مصفوفة من وحدات بايت تحتوي على المفتاح العام للاشتراك مفتاح عام محلي.

const keyLabel = new Buffer('P-256\0', 'utf8');

// Convert subscription public key into a buffer.
const subscriptionPubKey = new Buffer(subscription.keys.p256dh, 'base64');

const subscriptionPubKeyLength = new Uint8Array(2);
subscriptionPubKeyLength[0] = 0;
subscriptionPubKeyLength[1] = subscriptionPubKey.length;

const localPublicKeyLength = new Uint8Array(2);
subscriptionPubKeyLength[0] = 0;
subscriptionPubKeyLength[1] = localPublicKey.length;

const contextBuffer = Buffer.concat([
  keyLabel,
  subscriptionPubKeyLength.buffer,
  subscriptionPubKey,
  localPublicKeyLength.buffer,
  localPublicKey,
]);

المخزن المؤقت للسياق النهائي هو عبارة عن تسمية وعدد وحدات البايت في المفتاح العام للاشتراك متبوعًا بالمفتاح نفسه، ثم عدد وحدات البايت للمفتاح العام المحلي، متبوعًا بالمفتاح نفسها.

من خلال قيمة السياق هذه، يمكننا استخدامها في إنشاء مفتاح خاص ومفتاح تشفير المحتوى (CEK).

مفتاح تشفير المحتوى ومفتاح التشفير الخاص به

nonce هي قيمة تمنع إعادة التشغيل. الهجوم حيث يجب استخدامه مرة واحدة فقط.

مفتاح تشفير المحتوى (CEK) هو المفتاح الذي سيُستخدم في النهاية لتشفير حمولةنا.

نحتاج أولاً إلى إنشاء وحدات بايت من البيانات لـ nonce وCEK، وهو مجرد محتوى سلسلة ترميز متبوعة بالمخزن المؤقت للسياق الذي حسبناه للتو:

const nonceEncBuffer = new Buffer('Content-Encoding: nonce\0', 'utf8');
const nonceInfo = Buffer.concat([nonceEncBuffer, contextBuffer]);

const cekEncBuffer = new Buffer('Content-Encoding: aesgcm\0');
const cekInfo = Buffer.concat([cekEncBuffer, contextBuffer]);

يتم إدارة هذه المعلومات من خلال HKDF حيث تجمع بين الملح وPRK مع nonceInfo وcekInfo:

// The nonce should be 12 bytes long
const nonce = hkdf(salt, prk, nonceInfo, 12);

// The CEK should be 16 bytes long
const contentEncryptionKey = hkdf(salt, prk, cekInfo, 16);

نحصل على مفتاح التشفير الخاص بنا ومفتاح تشفير المحتوى.

إجراء التشفير

الآن بعد أن أصبح لدينا مفتاح تشفير المحتوى، يمكننا تشفير الحمولة.

ننشئ تشفير AES128 باستخدام مفتاح تشفير المحتوى كمفتاح وnonce هو متجه التهيئة.

في Node، يتم ذلك على النحو التالي:

const cipher = crypto.createCipheriv(
  'id-aes128-GCM',
  contentEncryptionKey,
  nonce,
);

قبل أن نشفِّر حمولة البيانات، نحتاج إلى تحديد مقدار المساحة المتروكة التي نريدها. لإضافتها إلى مقدمة الحمولة. السبب الذي يدفعنا لإضافة مساحة متروكة أنه يمنع خطر قدرة المتنصتين على تحديد "الأنواع" الرسائل بناءً على حجم حمولة البيانات.

يجب إضافة وحدتي بايت من المساحة المتروكة للإشارة إلى طول أي مساحة متروكة إضافية.

على سبيل المثال، إذا لم تضيف أي مساحة متروكة، سيكون لديك 2 بايت بالقيمة 0، أي لا توجد مساحة متروكة، وبعد هاتين البايتين ستتم قراءة الحمولة. إذا أضفت 5 بايت من المساحة المتروكة، ستكون قيمة أول بايتين 5، لذلك سيقرأ المستهلك خمس بايت إضافية ثم يبدأ في قراءة الحمولة.

const padding = new Buffer(2 + paddingLength);
// The buffer must be only zeros, except the length
padding.fill(0);
padding.writeUInt16BE(paddingLength, 0);

ثم نشغل المساحة المتروكة والحمولة من خلال هذا التشفير.

const result = cipher.update(Buffer.concat(padding, payload));
cipher.final();

// Append the auth tag to the result -
// https://nodejs.org/api/crypto.html#crypto_cipher_getauthtag
const encryptedPayload = Buffer.concat([result, cipher.getAuthTag()]);

لدينا الآن حمولة البيانات المشفّرة. رائع

كل ما يتبقى هو تحديد كيفية إرسال هذه الحمولة إلى خدمة الدفع.

رؤوس حمولة البيانات المشفّرة النص الأساسي

لإرسال هذه الحمولة المشفرة إلى خدمة الإرسال، نحتاج إلى تحديد بعض عناوين مختلفة في طلب POST.

عنوان التشفير

يشير مصطلح "Encryption" (التشفير) يجب أن يحتوي رأس الرسالة الإلكترونية على القيم العشوائية المستخدَم لتشفير الحمولة.

ويجب أن تكون البيانات العشوائية العشوائية بسعة 16 بايت بترميز آمن لعنوان URL الأساسي بترميز base64 وأن تتم إضافتها إلى عنوان التشفير، كما يلي:

Encryption: salt=[URL Safe Base64 Encoded Salt]

عنوان مفتاح التشفير

لاحظنا أنّه يتم استخدام العنوان Crypto-Key ضمن "مفاتيح خادم التطبيقات". أن تحتوي على مفتاح خادم التطبيقات العامة.

يُستخدم هذا العنوان أيضًا لمشاركة المفتاح العام المحلي المُستخدَم في التشفير. الحمولة.

يظهر العنوان الناتج على النحو التالي:

Crypto-Key: dh=[URL Safe Base64 Encoded Local Public Key String]; p256ecdsa=[URL Safe Base64 Encoded Public Application Server Key]

نوع المحتوى وطوله عناوين الترميز

العنوان Content-Length هو عدد وحدات البايت في ملف التشفير حمولة البيانات. "نوع المحتوى" و"Content-Encoding" (ترميز المحتوى) العناوين هي قيم ثابتة. يتم توضيح ذلك أدناه.

Content-Length: [Number of Bytes in Encrypted Payload]
Content-Type: 'application/octet-stream'
Content-Encoding: 'aesgcm'

باستخدام هذه العناوين، نحتاج إلى إرسال الحمولة المشفرة كنص طلبنا. لاحظ أنه تم ضبط Content-Type على application/octet-stream ويرجع ذلك إلى أنّ حمولة البيانات المشفّرة يجب أن تكون يتم إرساله في شكل تدفق من وحدات البايت.

في NodeJS، نفعل ذلك على النحو التالي:

const pushRequest = https.request(httpsOptions, function(pushResponse) {
pushRequest.write(encryptedPayload);
pushRequest.end();

هل المزيد من العناوين؟

لقد تناولنا العناوين المستخدمة لمفاتيح JWT / خادم التطبيق (مثل كيفية تحديد التطبيق مع خدمة الإرسال التلقائي) وقد تناولنا العناوين المستخدمة لإرسال الملفات حمولة البيانات.

هناك رؤوس إضافية تدفع الخدمات تستخدم لتغيير سلوك الرسائل المرسلة. بعض هذه العناوين مطلوبة، في حين أن البعض الآخر اختياري.

عنوان مدة البقاء (TTL)

مطلوب

TTL (أو مدة البقاء) هي عدد صحيح يحدد عدد الثواني. تريد نشر رسالتك الفورية في خدمة الدفع قبل أن تسليمه. عند انتهاء صلاحية TTL، ستتم إزالة الرسالة من قائمة انتظار خدمة الدفع ولن يتم تسليمها.

TTL: [Time to live in seconds]

في حال ضبط TTL على صفر، ستحاول خدمة الإرسال المباشر إرسال على الفور، ولكن إذا تعذر الوصول إلى الجهاز، فسيتم سيتم إسقاطها على الفور من قائمة انتظار خدمة الدفع.

من الناحية الفنية، يمكن للخدمة الفورية تقليل نسبة TTL للرسالة الفورية إذا كانت يريد. يمكنك معرفة ما إذا كان ذلك قد حدث عن طريق مراجعة عنوان TTL في الاستجابة من خدمة الدفع.

الموضوع

اختياريّ

المواضيع هي سلاسل يمكن استخدامها لاستبدال رسالة معلّقة بعلامة جديدة إذا كانت أسماء مواضيعها متطابقة.

ويكون ذلك مفيدًا في السيناريوهات التي يتم فيها إرسال رسائل متعددة أثناء الجهاز في وضع عدم اتصال، مما يعني أنك تريد حقًا أن يرى المستخدم أحدث إصدار عند تشغيل الجهاز.

حاجة ماسة

اختياريّ

يشير الإلحاح لخدمة الدفع إلى مدى أهمية الرسالة للمستخدم. هذا النمط من قبل خدمة الدفع للمساعدة في الحفاظ على عمر البطارية لجهاز المستخدم عن طريق الاستيقاظ لتلقي الرسائل المهمة عندما تكون البطارية منخفضة.

يتم تحديد قيمة العنوان كما هو موضّح أدناه. الإعداد التلقائي القيمة هي normal.

Urgency: [very-low | low | normal | high]

كل شيء معًا

إذا كانت لديك أسئلة إضافية حول كيفية تنفيذ كل هذه الإجراءات، يمكنك في أي وقت الاطّلاع على كيفية تشغيل المكتبات. الرسائل الفورية على web-push-libs org.

بعد توفُّر حمولة بيانات مشفّرة والعناوين أعلاه، ما عليك سوى تقديم طلب POST. إلى endpoint في PushSubscription.

إذًا، ماذا نفعل بالرد على طلب POST هذا؟

رد من خدمة الدفع

بعد تقديم طلب إلى خدمة الدفع الفوري، يجب التحقّق من رمز الحالة. من الرد إذ سيخبرك ما إذا كان الطلب ناجحًا أم لا.

رمز الحالة الوصف
201 تم الإنشاء. تم تلقّي طلب إرسال رسالة فورية وقبوله.
429 عدد الطلبات كبير جدًا. يعني ذلك أنّ خادم التطبيق قد وصل إلى معدّل. من خلال خدمة الدفع. يجب أن تتضمن خدمة الدفع "إعادة المحاولة بعد" للإشارة إلى المدة قبل إجراء طلب آخر.
400 الطلب غير صالح. يعني هذا بشكل عام أنّ أحد العناوين غير صالح. أو تم تنسيقه بشكل غير صحيح.
404 غير موجودة هذه إشارة إلى انتهاء صلاحية الاشتراك ولا يمكن استخدامها في هذه الحالة، يجب حذف "PushSUBSCRIPTION" وانتظر حتى يعيد العميل اشتراك المستخدم.
410 اختفت لم يعد الاشتراك صالحًا ويجب إزالته من خادم التطبيق. يمكن إعادة إنتاج ذلك عن طريق استدعاء "إلغاء الاشتراك() " في "PushSUBSCRIPTION"
413 حجم الحمولة كبير جدًا. الحد الأدنى لحجم الحمولة في خدمة الدفع حجم الدعم هو 4,096 بايت (أو 4 كيلوبايت).

الخطوات التالية

الدروس التطبيقية حول الترميز