{"meta":{"title":"Проверка доставки веб-перехватчика","intro":"Секрет веб-перехватчика можно использовать для проверки того, что доставка веб-перехватчика осуществляется из GitHub.","product":"Веб-перехватчики","breadcrumbs":[{"href":"/ru/webhooks","title":"Веб-перехватчики"},{"href":"/ru/webhooks/using-webhooks","title":"Использование веб-перехватчиков"},{"href":"/ru/webhooks/using-webhooks/validating-webhook-deliveries","title":"Проверка поставок"}],"documentType":"article"},"body":"# Проверка доставки веб-перехватчика\n\nСекрет веб-перехватчика можно использовать для проверки того, что доставка веб-перехватчика осуществляется из GitHub.\n\n## Проверка доставки веб-перехватчика\n\nПосле настройки сервера для получения полезных данных он будет прослушивать любую доставку, отправленную в настроенную конечную точку. Чтобы убедиться, что сервер обрабатывает только поставки веб-перехватчика, отправленные GitHub и чтобы убедиться, что доставка не была изменена, перед дальнейшей обработкой доставки необходимо проверить подпись веб-перехватчика. Это поможет избежать затрат на время сервера для обработки поставок, которые не относятся к GitHub и помогут избежать атак в середине.\n\nДля этого необходимо выполнить следующие действия.\n\n1. Создайте секретный маркер для веб-перехватчика.\n2. Безопасно храните маркер на сервере.\n3. Проверьте входящие полезные данные веб-перехватчика по маркеру, чтобы убедиться, что они приходят из GitHub и не были изменены.\n\n## Создание секретного токена\n\nВы можете создать новый веб-перехватчик с секретным маркером или добавить маркер секрета в существующий веб-перехватчик. При создании секретного токена следует выбрать случайную строку текста с высокой энтропией.\n\n* ```\n          _Чтобы создать новый веб-перехватчик с секретным маркером_, см. раздел [AUTOTITLE](/webhooks/using-webhooks/creating-webhooks).\n  ```\n* ```\n          _Чтобы добавить секретный маркер в существующий веб-перехватчик, измените параметры веб-перехватчика_. В разделе \"Секрет\" введите строку для использования в качестве `secret` ключа. Дополнительные сведения см. в разделе [AUTOTITLE](/webhooks/using-webhooks/editing-webhooks).\n  ```\n\n## Безопасное хранение маркера секрета\n\nПосле создания секретного маркера необходимо сохранить его в безопасном расположении, к которому может получить доступ сервер. Никогда не закодировать маркер в приложение или отправить маркер в любой репозиторий. Дополнительные сведения об безопасном использовании учетных данных проверки подлинности в коде см. в разделе [Обеспечение безопасности учетных данных API](/ru/rest/overview/keeping-your-api-credentials-secure#use-authentication-credentials-securely-in-your-code).\n\n## Проверка доставки веб-перехватчика\n\nGitHub будет использовать секретный маркер для создания хэш-подписи, отправленной вам с каждой полезной нагрузкой. Хэш-подпись будет отображаться в каждой доставке в качестве значения заголовка `X-Hub-Signature-256` . Дополнительные сведения см. в разделе [События и полезные данные веб-перехватчика](/ru/webhooks/webhook-events-and-payloads#delivery-headers).\n\nВ коде, который обрабатывает поставки веб-перехватчика, следует вычислить хэш с помощью секретного токена. Затем сравните хэш, который GitHub отправлен с ожидаемым хэшом, который вы вычислили, и убедитесь, что они соответствуют. Примеры проверки хэшей на различных языках программирования см [. в примерах](#examples).\n\nПри проверке полезных данных веб-перехватчика следует учитывать несколько важных моментов:\n\n* GitHub использует хэш-дайджест HMAC.\n* Хэш-подпись всегда начинается с `sha256=`.\n* Хэш-подпись создается с помощью секретного маркера веб-перехватчика и содержимого полезных данных.\n* Если в реализации языка и сервера указана кодировка символов, убедитесь, что полезные данные обрабатываются как символы UTF-8. Полезные данные веб-перехватчика могут содержать символы юникода.\n* Никогда не используйте обычный `==` оператор. Вместо этого рекомендуется использовать такой метод [`secure_compare`](https://www.rubydoc.info/gems/rack/Rack%2FUtils:secure_compare) или [`crypto.timingSafeEqual`](https://nodejs.org/api/crypto.html#cryptotimingsafeequala-b), который выполняет сравнение строк \"постоянного времени\" для устранения определенных атак времени на регулярные операторы равенства или регулярные циклы на языках, оптимизированных для JIT.\n\n### Тестирование проверки полезных данных веб-перехватчика\n\nДля проверки правильности реализации можно использовать следующие `secret` и `payload` значения:\n\n* ```\n          `secret`: `It's a Secret to Everybody`\n  ```\n* ```\n          `payload`: `Hello, World!`\n  ```\n\nЕсли реализация правильна, создаваемые подписи должны соответствовать следующим значениям подписи:\n\n* подпись: `757107ea0eb2509fc211221cce984b8a37570b6d7586c22c46f4379c8b043e17` <!-- markdownlint-disable-line GHD034 -->\n* X-Hub-Signature-256: `sha256=757107ea0eb2509fc211221cce984b8a37570b6d7586c22c46f4379c8b043e17`\n\n### Примеры\n\nВы можете использовать язык программирования для реализации проверки HMAC в коде. Ниже приведены некоторые примеры того, как реализация может выглядеть на различных языках программирования.\n\n#### Пример Ruby\n\nНапример, можно определить следующую `verify_signature` функцию:\n\n```ruby\ndef verify_signature(payload_body)\n  signature = 'sha256=' + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), ENV['SECRET_TOKEN'], payload_body)\n  return halt 500, \"Signatures didn't match!\" unless Rack::Utils.secure_compare(signature, request.env['HTTP_X_HUB_SIGNATURE_256'])\nend\n```\n\nЗатем его можно вызвать при получении полезных данных веб-перехватчика:\n\n```ruby\npost '/payload' do\n  request.body.rewind\n  payload_body = request.body.read\n  verify_signature(payload_body)\n  push = JSON.parse(payload_body)\n  \"I got some JSON: #{push.inspect}\"\nend\n```\n\n#### Пример Python\n\nНапример, можно определить следующую `verify_signature` функцию и вызвать ее при получении полезных данных веб-перехватчика:\n\n```python\nimport hashlib\nimport hmac\ndef verify_signature(payload_body, secret_token, signature_header):\n    \"\"\"Verify that the payload was sent from GitHub by validating SHA256.\n\n    Raise and return 403 if not authorized.\n\n    Args:\n        payload_body: original request body to verify (request.body())\n        secret_token: GitHub app webhook token (WEBHOOK_SECRET)\n        signature_header: header received from GitHub (x-hub-signature-256)\n    \"\"\"\n    if not signature_header:\n        raise HTTPException(status_code=403, detail=\"x-hub-signature-256 header is missing!\")\n    hash_object = hmac.new(secret_token.encode('utf-8'), msg=payload_body, digestmod=hashlib.sha256)\n    expected_signature = \"sha256=\" + hash_object.hexdigest()\n    if not hmac.compare_digest(expected_signature, signature_header):\n        raise HTTPException(status_code=403, detail=\"Request signatures didn't match!\")\n```\n\n#### Пример JavaScript\n\nНапример, можно определить следующую `verifySignature` функцию и вызвать ее в любой среде JavaScript при получении полезных данных веб-перехватчика:\n\n```javascript\nlet encoder = new TextEncoder();\n\nasync function verifySignature(secret, header, payload) {\n    let parts = header.split(\"=\");\n    let sigHex = parts[1];\n\n    let algorithm = { name: \"HMAC\", hash: { name: 'SHA-256' } };\n\n    let keyBytes = encoder.encode(secret);\n    let extractable = false;\n    let key = await crypto.subtle.importKey(\n        \"raw\",\n        keyBytes,\n        algorithm,\n        extractable,\n        [ \"sign\", \"verify\" ],\n    );\n\n    let sigBytes = hexToBytes(sigHex);\n    let dataBytes = encoder.encode(payload);\n    let equal = await crypto.subtle.verify(\n        algorithm.name,\n        key,\n        sigBytes,\n        dataBytes,\n    );\n\n    return equal;\n}\n\nfunction hexToBytes(hex) {\n    let len = hex.length / 2;\n    let bytes = new Uint8Array(len);\n\n    let index = 0;\n    for (let i = 0; i < hex.length; i += 2) {\n        let c = hex.slice(i, i + 2);\n        let b = parseInt(c, 16);\n        bytes[index] = b;\n        index += 1;\n    }\n\n    return bytes;\n}\n```\n\n#### Пример TypeScript\n\nНапример, можно определить следующую `verify_signature` функцию и вызвать ее при получении полезных данных веб-перехватчика:\n\n```javascript copy\nimport { Webhooks } from \"@octokit/webhooks\";\n\nconst webhooks = new Webhooks({\n  secret: process.env.WEBHOOK_SECRET,\n});\n\nconst handleWebhook = async (req, res) => {\n  const signature = req.headers[\"x-hub-signature-256\"];\n  const body = await req.text();\n\n  if (!(await webhooks.verify(body, signature))) {\n    res.status(401).send(\"Unauthorized\");\n    return;\n  }\n\n  // The rest of your logic here\n};\n```\n\n## Устранение неполадок\n\nЕсли вы уверены, что полезные данные находятся из GitHub, но проверка подписи завершается ошибкой:\n\n* Убедитесь, что вы настроили секрет для веб-перехватчика. Заголовок `X-Hub-Signature-256` не будет присутствовать, если вы не настроили секрет для веб-перехватчика. Дополнительные сведения о настройке секрета для веб-перехватчика см. в разделе [Редактирование веб-перехватчиков](/ru/webhooks/using-webhooks/editing-webhooks).\n* Убедитесь, что используется правильный заголовок. GitHub рекомендует использовать `X-Hub-Signature-256` заголовок, который использует алгоритм HMAC-SHA256. Заголовок `X-Hub-Signature` использует алгоритм HMAC-SHA1 и включается только в устаревшие цели.\n* Убедитесь, что используется правильный алгоритм. При использовании заголовка `X-Hub-Signature-256` следует использовать алгоритм HMAC-SHA256.\n* Убедитесь, что вы используете правильный секрет веб-перехватчика. Если вы не знаете значение секрета веб-перехватчика, вы можете обновить секрет веб-перехватчика. Дополнительные сведения см. в разделе [Редактирование веб-перехватчиков](/ru/webhooks/using-webhooks/editing-webhooks).\n* Убедитесь, что полезные данные и заголовки не изменяются перед проверкой. Например, если вы используете прокси-сервер или подсистему балансировки нагрузки, убедитесь, что прокси-сервер или подсистема балансировки нагрузки не изменяет полезные данные или заголовки.\n* Если в реализации языка и сервера указана кодировка символов, убедитесь, что полезные данные обрабатываются как символы UTF-8. Полезные данные веб-перехватчика могут содержать символы юникода.\n\n## Дополнительные материалы\n\n* ```\n          [AUTOTITLE](/webhooks/using-webhooks/handling-webhook-deliveries)\n  ```\n* ```\n          [AUTOTITLE](/webhooks/using-webhooks/best-practices-for-using-webhooks)\n  ```"}