HTTPS
[Стабильно: 2 - Стабильно]
Стабильно: 2 Стабильность: 2 - Стабильно
Исходный код: lib/https.js
HTTPS — это протокол HTTP поверх TLS/SSL. В Node.js он реализован как отдельный модуль.
Определение отсутствия поддержки криптографии
Node.js может быть собран без поддержки модуля node:crypto
. В таких случаях попытка импорта из https
или вызов require('node:https')
приведут к ошибке.
При использовании CommonJS ошибку можно перехватить с помощью try/catch:
let https
try {
https = require('node:https')
} catch (err) {
console.error('Поддержка https отключена!')
}
При использовании лексического ключевого слова ESM import
ошибку можно перехватить только в том случае, если обработчик для process.on('uncaughtException')
зарегистрирован до любой попытки загрузки модуля (например, с помощью модуля предварительной загрузки).
При использовании ESM, если существует вероятность того, что код может быть запущен в сборке Node.js, где поддержка криптографии не включена, рассмотрите возможность использования функции import()
вместо лексического ключевого слова import
:
let https
try {
https = await import('node:https')
} catch (err) {
console.error('Поддержка https отключена!')
}
Класс: https.Agent
[История]
Версия | Изменения |
---|---|
v5.3.0 | Поддержка 0 maxCachedSessions для отключения кэширования сеансов TLS. |
v2.5.0 | Параметр maxCachedSessions добавлен в options для повторного использования сеансов TLS. |
v0.4.5 | Добавлено в: v0.4.5 |
Объект Agent
для HTTPS, аналогичный http.Agent
. См. https.request()
для получения дополнительной информации.
new Agent([options])
[История]
Версия | Изменения |
---|---|
v12.5.0 | Не устанавливать автоматически имя сервера, если целевой хост был указан с использованием IP-адреса. |
options
<Объект> Набор настраиваемых параметров для установки в агенте. Может иметь те же поля, что и дляhttp.Agent(options)
, а такжеmaxCachedSessions
<число> максимальное количество кэшированных сеансов TLS. Используйте0
, чтобы отключить кэширование сеансов TLS. По умолчанию:100
.servername
<строка> значение расширения Server Name Indication, которое будет отправлено на сервер. Используйте пустую строку''
, чтобы отключить отправку расширения. По умолчанию: имя хоста целевого сервера, если только целевой сервер не указан с использованием IP-адреса, в этом случае значение по умолчанию —''
(расширение не отправляется). См.Возобновление сеанса
для получения информации о повторном использовании сеансов TLS.
Событие: 'keylog'
Добавлено в: v13.2.0, v12.16.0
line
<Buffer> Строка текста ASCII в формате NSSSSLKEYLOGFILE
.tlsSocket
<tls.TLSSocket> Экземплярtls.TLSSocket
, на котором он был сгенерирован.
Событие keylog
генерируется, когда ключевой материал создается или принимается соединением, управляемым этим агентом (обычно до завершения рукопожатия, но не обязательно). Этот ключевой материал может быть сохранен для отладки, поскольку он позволяет расшифровать перехваченный трафик TLS. Он может генерироваться несколько раз для каждого сокета.
Типичный случай использования — добавление принятых строк в общий текстовый файл, который позже используется программным обеспечением (таким как Wireshark) для расшифровки трафика:
// ...
https.globalAgent.on('keylog', (line, tlsSocket) => {
fs.appendFileSync('/tmp/ssl-keys.log', line, { mode: 0o600 })
})
Класс: https.Server
Добавлено в: v0.3.4
- Расширяет: <tls.Server>
См. http.Server
для получения дополнительной информации.
server.close([callback])
Добавлено в: v0.1.90
callback
<Function>- Возвращает: <https.Server>
См. server.close()
в модуле node:http
.
server[Symbol.asyncDispose]()
Добавлено в: v20.4.0
[Стабильно: 1 - Экспериментально]
Стабильно: 1 Стабильность: 1 - Экспериментально
Вызывает server.close()
и возвращает promise, который выполняется после закрытия сервера.
server.closeAllConnections()
Добавлено в: v18.2.0
См. server.closeAllConnections()
в модуле node:http
.
server.closeIdleConnections()
Добавлено в: v18.2.0
См. server.closeIdleConnections()
в модуле node:http
.
server.headersTimeout
Добавлен в: v11.3.0
- <число> По умолчанию:
60000
См. server.headersTimeout
в модуле node:http
.
server.listen()
Запускает HTTPS-сервер для прослушивания зашифрованных подключений. Этот метод идентичен server.listen()
из net.Server
.
server.maxHeadersCount
- <число> По умолчанию:
2000
См. server.maxHeadersCount
в модуле node:http
.
server.requestTimeout
[История]
Версия | Изменения |
---|---|
v18.0.0 | Время ожидания запроса по умолчанию изменено с неограниченного на 300 с (5 минут). |
v14.11.0 | Добавлено в: v14.11.0 |
- <число> По умолчанию:
300000
См. server.requestTimeout
в модуле node:http
.
server.setTimeout([msecs][, callback])
Добавлен в: v0.11.2
msecs
<число> По умолчанию:120000
(2 минуты)callback
<Функция>- Возвращает: <https.Server>
См. server.setTimeout()
в модуле node:http
.
server.timeout
[История]
Версия | Изменения |
---|---|
v13.0.0 | Время ожидания по умолчанию изменено с 120 с на 0 (неограниченное время ожидания). |
v0.11.2 | Добавлено в: v0.11.2 |
- <число> По умолчанию: 0 (неограниченное время ожидания)
См. server.timeout
в модуле node:http
.
server.keepAliveTimeout
Добавлено в: v8.0.0
- <число> По умолчанию:
5000
(5 секунд)
См. server.keepAliveTimeout
в модуле node:http
.
https.createServer([options][, requestListener])
Добавлено в: v0.3.4
options
<Объект> Принимаетoptions
отtls.createServer()
,tls.createSecureContext()
иhttp.createServer()
.requestListener
<Функция> Слушатель, который будет добавлен к событию'request'
.- Возвращает: <https.Server>
// curl -k https://localhost:8000/
import { createServer } from 'node:https'
import { readFileSync } from 'node:fs'
const options = {
key: readFileSync('private-key.pem'),
cert: readFileSync('certificate.pem'),
}
createServer(options, (req, res) => {
res.writeHead(200)
res.end('hello world\n')
}).listen(8000)
// curl -k https://localhost:8000/
const https = require('node:https')
const fs = require('node:fs')
const options = {
key: fs.readFileSync('private-key.pem'),
cert: fs.readFileSync('certificate.pem'),
}
https
.createServer(options, (req, res) => {
res.writeHead(200)
res.end('hello world\n')
})
.listen(8000)
Или
import { createServer } from 'node:https'
import { readFileSync } from 'node:fs'
const options = {
pfx: readFileSync('test_cert.pfx'),
passphrase: 'sample',
}
createServer(options, (req, res) => {
res.writeHead(200)
res.end('hello world\n')
}).listen(8000)
const https = require('node:https')
const fs = require('node:fs')
const options = {
pfx: fs.readFileSync('test_cert.pfx'),
passphrase: 'sample',
}
https
.createServer(options, (req, res) => {
res.writeHead(200)
res.end('hello world\n')
})
.listen(8000)
Для генерации сертификата и ключа для этого примера выполните:
openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' \
-keyout private-key.pem -out certificate.pem
Затем, для генерации сертификата pfx
для этого примера выполните:
openssl pkcs12 -certpbe AES-256-CBC -export -out test_cert.pfx \
-inkey private-key.pem -in certificate.pem -passout pass:sample
https.get(options[, callback])
https.get(url[, options][, callback])
[История]
Версия | Изменения |
---|---|
v10.9.0 | Теперь параметр url может передаваться вместе с отдельным объектом options . |
v7.5.0 | Параметр options может быть объектом WHATWG URL . |
v0.3.6 | Добавлено в: v0.3.6 |
url
<строка> | <URL>options
<Объект> | <строка> | <URL> Принимает те жеoptions
, что иhttps.request()
, при этом метод по умолчанию установлен как GET.callback
<Функция>
Аналогично http.get()
, но для HTTPS.
options
может быть объектом, строкой или объектом URL
. Если options
является строкой, она автоматически разбирается с помощью new URL()
. Если это объект URL
, он будет автоматически преобразован в обычный объект options
.
import { get } from 'node:https'
import process from 'node:process'
get('https://encrypted.google.com/', res => {
console.log('statusCode:', res.statusCode)
console.log('headers:', res.headers)
res.on('data', d => {
process.stdout.write(d)
})
}).on('error', e => {
console.error(e)
})
const https = require('node:https')
https
.get('https://encrypted.google.com/', res => {
console.log('statusCode:', res.statusCode)
console.log('headers:', res.headers)
res.on('data', d => {
process.stdout.write(d)
})
})
.on('error', e => {
console.error(e)
})
https.globalAgent
[История]
Версия | Изменения |
---|---|
v19.0.0 | Агент теперь использует HTTP Keep-Alive и таймаут 5 секунд по умолчанию. |
v0.5.9 | Добавлено в: v0.5.9 |
Глобальный экземпляр https.Agent
для всех HTTPS-запросов клиента. Отличается от конфигурации по умолчанию https.Agent
включенным keepAlive
и таймаутом в 5 секунд.
https.request(options[, callback])
https.request(url[, options][, callback])
[История]
Версия | Изменения |
---|---|
v22.4.0, v20.16.0 | Опция clientCertEngine зависит от поддержки пользовательского движка в OpenSSL, которая устарела в OpenSSL 3. |
v16.7.0, v14.18.0 | При использовании объекта URL имя пользователя и пароль теперь будут правильно декодированы URI. |
v14.1.0, v13.14.0 | Теперь принимается опция highWaterMark . |
v10.9.0 | Теперь параметр url может передаваться вместе с отдельным объектом options . |
v9.3.0 | Параметр options теперь может включать clientCertEngine . |
v7.5.0 | Параметр options может быть объектом WHATWG URL . |
v0.3.6 | Добавлено в: v0.3.6 |
options
<Объект> | <строка> | <URL> Принимает всеoptions
изhttp.request()
с некоторыми отличиями в значениях по умолчанию:protocol
По умолчанию:'https:'
port
По умолчанию:443
agent
По умолчанию:https.globalAgent
callback
<Функция>Возвращает: <http.ClientRequest>
Выполняет запрос к защищенному веб-серверу.
Также принимаются следующие дополнительные параметры options
из tls.connect()
: ca
, cert
, ciphers
, clientCertEngine
(устарело), crl
, dhparam
, ecdhCurve
, honorCipherOrder
, key
, passphrase
, pfx
, rejectUnauthorized
, secureOptions
, secureProtocol
, servername
, sessionIdContext
, highWaterMark
.
options
может быть объектом, строкой или объектом URL
. Если options
— строка, она автоматически разбирается с помощью new URL()
. Если это объект URL
, он будет автоматически преобразован в обычный объект options
.
https.request()
возвращает экземпляр класса http.ClientRequest
. Экземпляр ClientRequest
является записываемым потоком. Если необходимо загрузить файл с помощью POST-запроса, запишите данные в объект ClientRequest
.
import { request } from 'node:https'
import process from 'node:process'
const options = {
hostname: 'encrypted.google.com',
port: 443,
path: '/',
method: 'GET',
}
const req = request(options, res => {
console.log('statusCode:', res.statusCode)
console.log('headers:', res.headers)
res.on('data', d => {
process.stdout.write(d)
})
})
req.on('error', e => {
console.error(e)
})
req.end()
const https = require('node:https')
const options = {
hostname: 'encrypted.google.com',
port: 443,
path: '/',
method: 'GET',
}
const req = https.request(options, res => {
console.log('statusCode:', res.statusCode)
console.log('headers:', res.headers)
res.on('data', d => {
process.stdout.write(d)
})
})
req.on('error', e => {
console.error(e)
})
req.end()
Пример использования параметров из tls.connect()
:
const options = {
hostname: 'encrypted.google.com',
port: 443,
path: '/',
method: 'GET',
key: fs.readFileSync('private-key.pem'),
cert: fs.readFileSync('certificate.pem'),
}
options.agent = new https.Agent(options)
const req = https.request(options, res => {
// ...
})
В качестве альтернативы, отключите пул соединений, не используя Agent
.
const options = {
hostname: 'encrypted.google.com',
port: 443,
path: '/',
method: 'GET',
key: fs.readFileSync('private-key.pem'),
cert: fs.readFileSync('certificate.pem'),
agent: false,
}
const req = https.request(options, res => {
// ...
})
Пример использования URL
в качестве options
:
const options = new URL('https://abc:')
const req = https.request(options, res => {
// ...
})
Пример привязки к отпечатку сертификата или открытому ключу (аналогично pin-sha256
):
import { checkServerIdentity } from 'node:tls'
import { Agent, request } from 'node:https'
import { createHash } from 'node:crypto'
function sha256(s) {
return createHash('sha256').update(s).digest('base64')
}
const options = {
hostname: 'github.com',
port: 443,
path: '/',
method: 'GET',
checkServerIdentity: function (host, cert) {
// Убедитесь, что сертификат выдан для хоста, к которому мы подключены
const err = checkServerIdentity(host, cert)
if (err) {
return err
}
// Прикрепите открытый ключ, аналогично прикреплению HPKP pin-sha256
const pubkey256 = 'SIXvRyDmBJSgatgTQRGbInBaAK+hZOQ18UmrSwnDlK8='
if (sha256(cert.pubkey) !== pubkey256) {
const msg =
'Ошибка проверки сертификата: ' +
`Открытый ключ '${cert.subject.CN}' ` +
'не соответствует нашему прикрепленному отпечатку'
return new Error(msg)
}
// Прикрепите точный сертификат, а не открытый ключ
const cert256 =
'FD:6E:9B:0E:F3:98:BC:D9:04:C3:B2:EC:16:7A:7B:' + '0F:DA:72:01:C9:03:C5:3A:6A:6A:E5:D0:41:43:63:EF:65'
if (cert.fingerprint256 !== cert256) {
const msg =
'Ошибка проверки сертификата: ' +
`Сертификат '${cert.subject.CN}' ` +
'не соответствует нашему прикрепленному отпечатку'
return new Error(msg)
}
// Этот цикл служит только для информационных целей.
// Выведите отпечатки сертификата и открытого ключа всех сертификатов в
// цепочке. Обычно открытый ключ эмитента прикрепляется в публичном
// интернете, а открытый ключ службы — в чувствительных
// средах.
let lastprint256
do {
console.log('Общее имя субъекта:', cert.subject.CN)
console.log(' Отпечаток SHA256 сертификата:', cert.fingerprint256)
const hash = createHash('sha256')
console.log(' Прикрепление открытого ключа ping-sha256:', sha256(cert.pubkey))
lastprint256 = cert.fingerprint256
cert = cert.issuerCertificate
} while (cert.fingerprint256 !== lastprint256)
},
}
options.agent = new Agent(options)
const req = request(options, res => {
console.log('Все ОК. Сервер соответствует нашему прикрепленному сертификату или открытому ключу')
console.log('statusCode:', res.statusCode)
res.on('data', d => {})
})
req.on('error', e => {
console.error(e.message)
})
req.end()
const tls = require('node:tls')
const https = require('node:https')
const crypto = require('node:crypto')
function sha256(s) {
return crypto.createHash('sha256').update(s).digest('base64')
}
const options = {
hostname: 'github.com',
port: 443,
path: '/',
method: 'GET',
checkServerIdentity: function (host, cert) {
// Убедитесь, что сертификат выдан для хоста, к которому мы подключены
const err = tls.checkServerIdentity(host, cert)
if (err) {
return err
}
// Прикрепите открытый ключ, аналогично прикреплению HPKP pin-sha256
const pubkey256 = 'SIXvRyDmBJSgatgTQRGbInBaAK+hZOQ18UmrSwnDlK8='
if (sha256(cert.pubkey) !== pubkey256) {
const msg =
'Ошибка проверки сертификата: ' +
`Открытый ключ '${cert.subject.CN}' ` +
'не соответствует нашему прикрепленному отпечатку'
return new Error(msg)
}
// Прикрепите точный сертификат, а не открытый ключ
const cert256 =
'FD:6E:9B:0E:F3:98:BC:D9:04:C3:B2:EC:16:7A:7B:' + '0F:DA:72:01:C9:03:C5:3A:6A:6A:E5:D0:41:43:63:EF:65'
if (cert.fingerprint256 !== cert256) {
const msg =
'Ошибка проверки сертификата: ' +
`Сертификат '${cert.subject.CN}' ` +
'не соответствует нашему прикрепленному отпечатку'
return new Error(msg)
}
// Этот цикл служит только для информационных целей.
// Выведите отпечатки сертификата и открытого ключа всех сертификатов в
// цепочке. Обычно открытый ключ эмитента прикрепляется в публичном
// интернете, а открытый ключ службы — в чувствительных
// средах.
do {
console.log('Общее имя субъекта:', cert.subject.CN)
console.log(' Отпечаток SHA256 сертификата:', cert.fingerprint256)
hash = crypto.createHash('sha256')
console.log(' Прикрепление открытого ключа ping-sha256:', sha256(cert.pubkey))
lastprint256 = cert.fingerprint256
cert = cert.issuerCertificate
} while (cert.fingerprint256 !== lastprint256)
},
}
options.agent = new https.Agent(options)
const req = https.request(options, res => {
console.log('Все ОК. Сервер соответствует нашему прикрепленному сертификату или открытому ключу')
console.log('statusCode:', res.statusCode)
res.on('data', d => {})
})
req.on('error', e => {
console.error(e.message)
})
req.end()
Вывод примера:
Общее имя субъекта: github.com
Отпечаток SHA256 сертификата: FD:6E:9B:0E:F3:98:BC:D9:04:C3:B2:EC:16:7A:7B:0F:DA:72:01:C9:03:C5:3A:6A:6A:E5:D0:41:43:63:EF:65
Прикрепление открытого ключа ping-sha256: SIXvRyDmBJSgatgTQRGbInBaAK+hZOQ18UmrSwnDlK8=
Общее имя субъекта: Sectigo ECC Domain Validation Secure Server CA
Отпечаток SHA256 сертификата: 61:E9:73:75:E9:F6:DA:98:2F:F5:C1:9E:2F:94:E6:6C:4E:35:B6:83:7C:E3:B9:14:D2:24:5C:7F:5F:65:82:5F
Прикрепление открытого ключа ping-sha256: Eep0p/AsSa9lFUH6KT2UY+9s1Z8v7voAPkQ4fGknZ2g=
Общее имя субъекта: USERTrust ECC Certification Authority
Отпечаток SHA256 сертификата: A6:CF:64:DB:B4:C8:D5:FD:19:CE:48:89:60:68:DB:03:B5:33:A8:D1:33:6C:62:56:A8:7D:00:CB:B3:DE:F3:EA
Прикрепление открытого ключа ping-sha256: UJM2FOhG9aTNY0Pg4hgqjNzZ/lQBiMGRxPD5Y2/e0bw=
Общее имя субъекта: AAA Certificate Services
Отпечаток SHA256 сертификата: D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4
Прикрепление открытого ключа ping-sha256: vRU+17BDT2iGsXvOi76E7TQMcTLXAqj0+jGPdW7L1vM=
Все ОК. Сервер соответствует нашему прикрепленному сертификату или открытому ключу
statusCode: 200