웹 푸시 프로토콜

라이브러리를 사용하여 푸시 메시지를 트리거하는 방법은 살펴보았지만 이 라이브러리들이 정확히 어떤 일을 하고 있을까요?

글쎄요, 그들은 네트워크 요청을 하면서 그러한 요청이 확실히 있습니다. 이 네트워크 요청을 정의하는 사양은 웹 푸시 프로토콜.

서버에서 푸시로 푸시 메시지를 전송하는 다이어그램
서비스

이 섹션에서는 서버가 애플리케이션을 사용하여 자신을 식별하는 방법을 설명합니다. 암호화된 페이로드 및 관련 데이터가 전송되는 방식을 설명합니다.

웹 푸시의 면이 나쁘거나 암호화 전문가는 아니지만 한번 살펴보겠습니다. 이러한 라이브러리가 내부적으로 무엇을 하는지 알 수 있으므로 편리합니다.

애플리케이션 서버 키

사용자를 구독하면 applicationServerKey를 전달합니다. 이 키는 푸시 서비스로 전달되어 푸시 알림을 받은 애플리케이션이 푸시 메시지를 트리거하는 애플리케이션이기도 합니다.

푸시 메시지를 트리거할 때 우리가 보내는 헤더 집합이 있습니다. 푸시 서비스가 애플리케이션을 인증하도록 합니다 (이는 VAPID 사양에 따름).

이 모든 것이 실제로 의미하는 바는 무엇이며 정확히 어떻게 일어날까요? 지금까지 애플리케이션 서버 인증:

  1. 애플리케이션 서버는 비공개 애플리케이션 키로 일부 JSON 정보에 서명합니다.
  2. 이렇게 서명된 정보는 POST 요청의 헤더로 푸시 서비스에 전송됩니다.
  3. 푸시 서비스는 pushManager.subscribe(): 수신된 정보가 공개 키와 관련된 비공개 키를 반환합니다. 주의: 공개 키는 구독 호출에 전달된 applicationServerKey입니다.
  4. 서명된 정보가 유효하면 푸시 서비스는 메시지를 사용자에게 보냅니다.

다음은 이러한 정보 흐름의 예입니다. (왼쪽 하단의 범례에서 공개 및 개인 키.)

비공개 애플리케이션 서버 키가
메시지

'signed information' JSON 웹 토큰이 요청의 헤더에 추가됩니다

JSON 웹 토큰

JSON 웹 토큰 (줄여서 JWT)은 수신자가 확인할 수 있도록 제3자에게 메시지를 전송하는 것은 있습니다.

서드 파티는 메일을 받으면 발신자를 가져와야 합니다. 공개 키를 사용하여 JWT의 서명을 검증하는 데 사용할 수 있습니다. 만약 서명이 유효하면 JWT가 일치하는 서명을 사용하여 서명되어야 합니다. 비공개 키이므로 예상 발신자가 보낸 것이어야 합니다.

https://jwt.io/에는 서명해 드릴 수 있습니다. 이 작업을 수행하려면 할 수 있습니다 완성도를 높이기 위해 서명된 JWT를 수동으로 만드는 방법을 살펴보겠습니다.

웹 푸시 및 서명된 JWT

서명된 JWT는 단순한 문자열이지만 세 개의 문자열이 결합된 것으로 생각할 수 있습니다. 표시해 줍니다.

JSON 웹의 문자열을 보여주는 삽화
토큰

첫 번째 문자열과 두 번째 문자열 (JWT 정보 및 JWT 데이터)은 base64로 인코딩된 JSON으로, 공개적으로 읽을 수 있습니다.

첫 번째 문자열은 JWT 자체에 대한 정보로, 어떤 알고리즘을 실행할지 나타냅니다. 서명을 생성하는 데 사용되었습니다.

웹 푸시를 위한 JWT 정보에는 다음 정보가 포함되어야 합니다.

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

두 번째 문자열은 JWT 데이터입니다. 이는 JWT를 보낸 사람에 대한 정보를 제공합니다. 유효한 기간입니다

웹 푸시의 경우 데이터 형식은 다음과 같습니다.

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

aud 값은 'audience'(즉, JWT의 대상)입니다. 웹의 경우 대상은 푸시 서비스이므로 푸시의 출처로 서비스를 사용합니다.

exp 값은 JWT의 만료로, 이를 통해 스누퍼가 JWT를 가로채면 재사용할 수 있습니다. 만료 시간은 초이며 더 이상 24시간이 아니어야 합니다.

Node.js에서 만료는 다음을 사용하여 설정됩니다.

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

24시간이 아닌 12시간이 지나면 전송 애플리케이션과 푸시 서비스 간의 클록 차이와 관련된 문제

마지막으로 sub 값은 URL 또는 mailto 이메일 주소여야 합니다. 이는 푸시 서비스가 발신자에게 연락해야 하는 경우 연락처 정보를 가져올 수도 있습니다 (이 때문에 웹 푸시 라이브러리에는 이메일 주소).

JWT 정보와 마찬가지로 JWT 데이터는 URL 보안 base64로 인코딩됩니다. 문자열.

세 번째 문자열인 서명은 처음 두 문자열을 가져온 결과입니다. (JWT 정보 및 JWT 데이터)를 사용하여 점 문자로 결합합니다. 나중에 설명하겠습니다. 'unsigned token'을 호출하고 서명합니다.

서명 프로세스에서 '서명되지 않은 토큰' 암호화 필요 할 수 있습니다. JWT에 따르면 ES256은 "P-256 곡선을 사용하는 ECDSA"의 줄임말입니다. 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 (즉, 점으로 결합된 세 개의 문자열 모두)가 웹으로 전송됩니다. 다음과 같이 앞에 WebPush가 추가된 Authorization 헤더로 서비스를 푸시합니다.

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

웹 푸시 프로토콜은 또한 공개 애플리케이션 서버 키가 Crypto-Key 헤더에 URL 안전 base64 인코딩 문자열로 전송 앞에 p256ecdsa=이(가) 추가되었습니다.

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

페이로드 암호화

다음으로 푸시 메시지를 통해 페이로드를 전송하여 웹 앱이 푸시 메시지를 받으면 수신한 데이터에 액세스할 수 있습니다.

다른 푸시 서비스를 사용해 본 사람이라면 누구나 왜 웹이 푸시 알림을 푸시하고 암호화해야 하나요? 네이티브 앱에서는 푸시 메시지가 일반 텍스트로 데이터를 전송할 수 있습니다.

웹 푸시의 장점 중 하나는 모든 푸시 서비스가 동일한 API (웹 푸시 프로토콜)를 기반으로 하므로 개발자는 누가 보여줍니다 올바른 형식으로 요청을 할 수 있으며 전송됩니다. 단점은 개발자가 신뢰할 수 없는 푸시 서비스로 메시지를 보내는 경우가 많습니다. 작성자: 페이로드를 암호화하면 푸시 서비스는 전송된 데이터를 읽을 수 없습니다. 브라우저만 정보를 복호화할 수 있습니다. 이렇게 하면 사용자의 데이터를 수집하는 데 사용됩니다

페이로드의 암호화는 메시지 암호화 사양을 참조하세요.

푸시 메시지 페이로드를 암호화하는 구체적인 단계를 살펴보기 전에 암호화 중에 사용할 몇 가지 기술을 다루겠습니다. 프로세스입니다 (Mat Scales에게 푸시에 대한 훌륭한 글을 소개하기 위해 커다란 모자에 대한 팁을 얻음 encryption.)

ECDH 및 HKDF

ECDH와 HKDF 모두 암호화 프로세스 전반에 사용되며 암호화 목적으로 사용됩니다.

ECDH: 타원 곡선 디피-헬만 키 교환

앨리스와 밥이라는 두 사람이 정보를 공유하려고 한다고 가정해 보겠습니다. 윤아와 정민은 모두 각자의 공개 키와 비공개 키를 가지고 있습니다. 윤아와 밥 서로 공개 키를 공유합니다

ECDH로 생성된 키의 유용한 특성은 앨리스가 비공개 키와 Bob의 공개 키를 사용하여 보안 비밀 값 'X'를 만듭니다. 밥이 할 수 있는 작업 마찬가지로, 자신의 비공개 키와 앨리스의 공개 키를 동일한 값 'X'를 생성합니다. 그러면 'X'가 됩니다. 공유 비밀번호 Alice와 Bob의 공개 키만 공유하면 됩니다. 이제 밥과 앨리스가 'X' 사용 가능 그들 사이의 메시지를 암호화하고 복호화합니다

ECDH는 제가 아는 한도 내에서 이 '특성'을 허용하는 곡선의 속성을 정의합니다. 공유 비밀 'X'를 만드는 것입니다.

ECDH에 대한 대략적인 설명입니다. 자세히 알아보려면 이 동영상을 시청하시기 바랍니다.

코드의 경우 대부분의 언어 / 플랫폼은 쉽게 생성할 수 있습니다

노드에서 다음을 실행합니다.

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

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

HKDF: HMAC 기반 키 파생 함수

Wikipedia에는 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);
}

이 예시 코드에 대한 Mat Scale의 도움말을 참고하세요.

ECDH를 대략적으로 다룹니다. 및 HKDF를 제공합니다.

ECDH는 공개 키를 공유하고 공유 보안 비밀을 생성하는 안전한 방법입니다. HKDF는 안전하게 만드는 것입니다.

이 정보는 페이로드 암호화 중에 사용됩니다. 다음으로 Google에서 생각하는 암호화 방식을 선택할 수 있습니다.

입력

페이로드가 포함된 사용자에게 푸시 메시지를 보내려면 다음 세 가지 입력이 필요합니다.

  1. 페이로드 자체
  2. PushSubscriptionauth 보안 비밀
  3. PushSubscriptionp256dh

authp256dh 값이 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 (유사 랜덤 키)는 푸시 구독의 인증 조합입니다. 방금 만든 공유 보안 비밀이 있습니다

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,
]);

최종 컨텍스트 버퍼는 라벨, 구독 공개 키의 바이트 수, 그 뒤에 키 자체, 로컬 공개 키의 바이트 수, 키 있습니다.

이 컨텍스트 값으로 nonce와 콘텐츠 암호화 키를 만들 때 사용할 수 있습니다. (CEK).

콘텐츠 암호화 키 및 nonce

nonce는 재생을 방지하는 값입니다. 한 번만 사용해야 하므로

콘텐츠 암호화 키 (CEK)는 결국 페이로드를 암호화하는 데 사용되는 키입니다.

먼저 nonce와 CEK의 데이터 바이트를 만들어야 합니다. 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]);

이 정보는 솔트와 PRK를 nonceInfo 및 cekInfo와 결합한 HKDF를 통해 실행됩니다.

// 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);

이렇게 하면 nonce와 콘텐츠 암호화 키가 제공됩니다.

암호화 수행

이제 콘텐츠 암호화 키가 있으므로 페이로드를 암호화할 수 있습니다.

콘텐츠 암호화 키를 사용하여 AES128 암호화를 만듭니다. 를 키로 사용하고 nonce는 초기화 벡터입니다.

Node에서는 이 작업이 다음과 같이 수행됩니다.

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

페이로드를 암호화하기 전에 원하는 패딩의 양을 정의해야 합니다. 페이로드 앞에 추가합니다 패딩을 추가하려는 이유는 이를 통해 도청자가 다른 해커의 공격을 파악할 수 있는 위험을 '유형' 메시지 수를 표시합니다

추가 패딩의 길이를 나타내려면 2바이트의 패딩을 추가해야 합니다.

예를 들어 패딩을 추가하지 않으면 값이 0인 2바이트가 생깁니다.즉, 패딩이 없습니다. 이 2바이트 이후에는 페이로드를 읽습니다. 패딩을 5바이트 추가하면 처음 2바이트의 값은 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()]);

이제 암호화된 페이로드가 생겼습니다. 와!

이제 남은 것은 이 페이로드가 푸시 서비스로 전송되는 방식을 결정하는 것입니다.

암호화된 페이로드 헤더 및 본문

이 암호화된 페이로드를 푸시 서비스로 보내려면 다른 헤더를 포함하는 것입니다.

암호화 헤더

'암호화' 헤더에는 페이로드 암호화에 사용된 솔트가 포함되어야 합니다.

16바이트 솔트는 다음과 같이 base64 URL로 안전하게 인코딩되고 암호화 헤더에 추가되어야 합니다.

Encryption: salt=[URL Safe Base64 Encoded Salt]

Crypto-Key 헤더

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'

이러한 헤더를 설정한 상태에서 암호화된 페이로드를 본문으로 전송해야 합니다. Google에서 접수한 요청입니다. Content-Type가 다음과 같이 설정되어 있습니다. application/octet-stream 이는 암호화된 페이로드가 바이트 스트림으로 전송됩니다.

NodeJS에서는 다음과 같이 할 수 있습니다.

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

헤더가 더 있나요?

JWT / 애플리케이션 서버 키에 사용되는 헤더에 대해 다루었습니다 (즉, 암호화하고 암호화된 데이터를 전송하는 데 사용되는 헤더에 대해 페이로드가 포함되어 있습니다

푸시 서비스가 보낸 메일입니다. 이러한 헤더 중 일부는 필수사항이지만, 선택사항인 헤더도 있습니다.

TTL 헤더

필수

TTL (또는 TTL)는 초를 지정하는 정수입니다. 푸시 메시지를 푸시 서비스에 합니다. TTL가 만료되면 메시지가 전달되지 않습니다

TTL: [Time to live in seconds]

TTL를 0으로 설정하면 푸시 서비스는 즉시 메시지를 보내지만 기기에 연결할 수 없는 경우에는 푸시 서비스 큐에서 즉시 삭제됩니다.

기술적으로 푸시 서비스는 다음과 같은 경우 푸시 메시지의 TTL를 줄일 수 있습니다. 있습니다. 다음에서 TTL 헤더를 검사하여 이러한 문제가 발생했는지 알 수 있습니다. 푸시 서비스의 응답을 반환합니다

주제

선택사항

주제는 대기 중인 메시지를 새 메시지가 표시됩니다.

이렇게 하면 여러 메시지가 동시에 전송되는 동안 사용자가 최신 기기만 볼 수 있도록 하려는 경우 메시지가 표시될 수 있습니다.

긴급

선택사항

긴급성은 메시지가 사용자에게 얼마나 중요한지를 푸시 서비스에 나타냅니다. 이 푸시 서비스에 의해 사용자 기기의 배터리 수명을 보존하는 데 절전 모드를 해제하여 중요한 메시지를 확인합니다.

헤더 값은 아래와 같이 정의됩니다. 기본값은 normal입니다.

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

모든 기능을 한곳에서 사용

이 모든 것이 어떻게 작동하는지 더 궁금한 점이 있으면 언제든지 라이브러리가 트리거되는 방식을 확인할 수 있습니다. 푸시 메시지를 web-push-libs org에서 푸시할 수 있습니다.

암호화된 페이로드와 위의 헤더가 있으면 POST 요청을 하기만 하면 됩니다. PushSubscriptionendpoint에 전달합니다.

그렇다면 이 POST 요청에 대한 응답으로 무엇을 해야 할까요?

푸시 서비스의 응답

푸시 서비스에 요청을 한 후에는 상태 코드를 확인해야 합니다. 요청이 성공했는지 여부를 알려줍니다. 알 수 있습니다.

상태 코드 설명
201 생성됨 푸시 메시지 전송 요청이 수신 및 수락되었습니다.
429 요청이 너무 많습니다. 애플리케이션 서버가 특정 속도에 푸시 서비스로 제공합니다 푸시 서비스에는 'Retry-After' 헤더를 사용하여 다른 요청을 할 수 있는 데 걸리는 시간을 나타냅니다.
400 요청이 잘못되었습니다. 일반적으로 헤더 중 하나가 유효하지 않음을 의미합니다. 잘못된 형식일 수 있습니다.
404 찾을 수 없음 구독이 만료되었음을 나타냅니다. 사용할 수 없습니다 이 경우 `PushSubscription` 클라이언트가 사용자를 다시 구독할 때까지 기다립니다.
410 사라졌다. 구독이 더 이상 유효하지 않으므로 삭제해야 합니다. 애플리케이션 서버에서 실행됩니다. 이는 `PushSubscription`의 `unsubscribe()`
413 페이로드 크기가 너무 큽니다. 푸시 서비스가 필요로 하는 최소 크기 페이로드 4,096바이트가 지원됩니다. (또는 4kb)입니다.

다음에 수행할 작업

Codelab