HTTPS
[Stabile: 2 - Stabile]
Stabile: 2 Stabilità: 2 - Stabile
Codice sorgente: lib/https.js
HTTPS è il protocollo HTTP su TLS/SSL. In Node.js, questo è implementato come un modulo separato.
Determinare se il supporto per la crittografia non è disponibile
È possibile che Node.js venga compilato senza includere il supporto per il modulo node:crypto
. In tali casi, il tentativo di importare
da https
o di chiamare require('node:https')
comporterà la generazione di un errore.
Quando si utilizza CommonJS, l'errore generato può essere intercettato utilizzando try/catch:
let https
try {
https = require('node:https')
} catch (err) {
console.error('Il supporto HTTPS è disabilitato!')
}
Quando si utilizza la parola chiave lessicale ESM import
, l'errore può essere intercettato solo se viene registrato un gestore per process.on('uncaughtException')
prima di qualsiasi tentativo di caricare il modulo (utilizzando, ad esempio, un modulo preload).
Quando si utilizza ESM, se esiste la possibilità che il codice venga eseguito su una build di Node.js in cui il supporto per la crittografia non è abilitato, si consiglia di utilizzare la funzione import()
invece della parola chiave lessicale import
:
let https
try {
https = await import('node:https')
} catch (err) {
console.error('Il supporto HTTPS è disabilitato!')
}
Classe: https.Agent
[Cronologia]
Versione | Modifiche |
---|---|
v5.3.0 | supporto 0 maxCachedSessions per disabilitare la memorizzazione nella cache delle sessioni TLS. |
v2.5.0 | parametro maxCachedSessions aggiunto a options per il riutilizzo delle sessioni TLS. |
v0.4.5 | Aggiunto in: v0.4.5 |
Un oggetto Agent
per HTTPS simile a http.Agent
. Vedere https.request()
per ulteriori informazioni.
new Agent([options])
[Cronologia]
Versione | Modifiche |
---|---|
v12.5.0 | non impostare automaticamente servername se l'host di destinazione è stato specificato utilizzando un indirizzo IP. |
options
<Object> Insieme di opzioni configurabili da impostare sull'agente. Può avere gli stessi campi dihttp.Agent(options)
, emaxCachedSessions
<number> numero massimo di sessioni TLS memorizzate nella cache. Utilizzare0
per disabilitare la memorizzazione nella cache delle sessioni TLS. Predefinito:100
.servername
<string> il valore dell'estensione Server Name Indication da inviare al server. Utilizzare una stringa vuota''
per disabilitare l'invio dell'estensione. Predefinito: nome host del server di destinazione, a meno che il server di destinazione non venga specificato utilizzando un indirizzo IP, nel qual caso il valore predefinito è''
(nessuna estensione). VedereRipresa sessione
per informazioni sul riutilizzo delle sessioni TLS.
Evento: 'keylog'
Aggiunto in: v13.2.0, v12.16.0
line
<Buffer> Riga di testo ASCII, nel formato NSSSSLKEYLOGFILE
.tlsSocket
<tls.TLSSocket> L'istanza ditls.TLSSocket
sulla quale è stato generato.
L'evento keylog
viene emesso quando il materiale di crittografia viene generato o ricevuto da una connessione gestita da questo agent (tipicamente prima che l'handshake sia completato, ma non necessariamente). Questo materiale di crittografia può essere memorizzato per il debug, poiché consente di decrittografare il traffico TLS catturato. Può essere emesso più volte per ogni socket.
Un tipico caso d'uso è aggiungere le righe ricevute a un file di testo comune, che viene successivamente utilizzato da software (come Wireshark) per decrittografare il traffico:
// ...
https.globalAgent.on('keylog', (line, tlsSocket) => {
fs.appendFileSync('/tmp/ssl-keys.log', line, { mode: 0o600 })
})
Classe: https.Server
Aggiunto in: v0.3.4
- Estende: <tls.Server>
Vedi http.Server
per maggiori informazioni.
server.close([callback])
Aggiunto in: v0.1.90
callback
<Function>- Restituisce: <https.Server>
Vedi server.close()
nel modulo node:http
.
server[Symbol.asyncDispose]()
Aggiunto in: v20.4.0
[Stabile: 1 - Sperimentale]
Stabile: 1 Stabilità: 1 - Sperimentale
Chiama server.close()
e restituisce una promise che si risolve quando il server si è chiuso.
server.closeAllConnections()
Aggiunto in: v18.2.0
Vedi server.closeAllConnections()
nel modulo node:http
.
server.closeIdleConnections()
Aggiunto in: v18.2.0
Vedi server.closeIdleConnections()
nel modulo node:http
.
server.headersTimeout
Aggiunto in: v11.3.0
- <number> Predefinito:
60000
Vedi server.headersTimeout
nel modulo node:http
.
server.listen()
Avvia il server HTTPS in ascolto di connessioni crittografate. Questo metodo è identico a server.listen()
da net.Server
.
server.maxHeadersCount
- <number> Predefinito:
2000
Vedi server.maxHeadersCount
nel modulo node:http
.
server.requestTimeout
[Cronologia]
Versione | Modifiche |
---|---|
v18.0.0 | Il timeout predefinito della richiesta è cambiato da nessun timeout a 300 secondi (5 minuti). |
v14.11.0 | Aggiunto in: v14.11.0 |
- <number> Predefinito:
300000
Vedi server.requestTimeout
nel modulo node:http
.
server.setTimeout([msecs][, callback])
Aggiunto in: v0.11.2
msecs
<number> Predefinito:120000
(2 minuti)callback
<Function>- Restituisce: <https.Server>
Vedi server.setTimeout()
nel modulo node:http
.
server.timeout
[Cronologia]
Versione | Modifiche |
---|---|
v13.0.0 | Il timeout predefinito è cambiato da 120 secondi a 0 (nessun timeout). |
v0.11.2 | Aggiunto in: v0.11.2 |
- <number> Predefinito: 0 (nessun timeout)
Vedi server.timeout
nel modulo node:http
.
server.keepAliveTimeout
Aggiunto in: v8.0.0
- <number> Predefinito:
5000
(5 secondi)
Vedi server.keepAliveTimeout
nel modulo node:http
.
https.createServer([options][, requestListener])
Aggiunto in: v0.3.4
options
<Object> Accettaoptions
datls.createServer()
,tls.createSecureContext()
ehttp.createServer()
.requestListener
<Function> Un listener da aggiungere all'evento'request'
.- Restituisce: <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)
Oppure
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)
Per generare il certificato e la chiave per questo esempio, eseguire:
openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' \
-keyout private-key.pem -out certificate.pem
Quindi, per generare il certificato pfx
per questo esempio, eseguire:
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])
[Cronologia]
Versione | Cambiamenti |
---|---|
v10.9.0 | Il parametro url ora può essere passato insieme a un oggetto options separato. |
v7.5.0 | Il parametro options può essere un oggetto URL WHATWG. |
v0.3.6 | Aggiunto in: v0.3.6 |
url
<stringa> | <URL>options
<Oggetto> | <stringa> | <URL> Accetta le stesseoptions
dihttps.request()
, con il metodo impostato su GET per impostazione predefinita.callback
<Funzione>
Come http.get()
ma per HTTPS.
options
può essere un oggetto, una stringa o un oggetto URL
. Se options
è una stringa, viene analizzata automaticamente con new URL()
. Se è un oggetto URL
, verrà automaticamente convertito in un normale oggetto 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
[Cronologia]
Versione | Modifiche |
---|---|
v19.0.0 | L'agent ora utilizza HTTP Keep-Alive e un timeout di 5 secondi per impostazione predefinita. |
v0.5.9 | Aggiunto in: v0.5.9 |
Istanza globale di https.Agent
per tutte le richieste client HTTPS. Si discosta da una configurazione predefinita di https.Agent
per avere keepAlive
abilitato e un timeout
di 5 secondi.
https.request(options[, callback])
https.request(url[, options][, callback])
[Cronologia]
Versione | Modifiche |
---|---|
v22.4.0, v20.16.0 | L'opzione clientCertEngine dipende dal supporto di motori personalizzati in OpenSSL, che è deprecato in OpenSSL 3. |
v16.7.0, v14.18.0 | Quando si utilizza un oggetto URL , il nome utente e la password analizzati verranno ora decodificati correttamente dall'URI. |
v14.1.0, v13.14.0 | L'opzione highWaterMark è ora accettata. |
v10.9.0 | Il parametro url può ora essere passato insieme a un oggetto options separato. |
v9.3.0 | Il parametro options può ora includere clientCertEngine . |
v7.5.0 | Il parametro options può essere un oggetto URL WHATWG. |
v0.3.6 | Aggiunto in: v0.3.6 |
url
<stringa> | <URL>options
<Oggetto> | <stringa> | <URL> Accetta tutte leoptions
dahttp.request()
, con alcune differenze nei valori predefiniti:protocol
Predefinito:'https:'
port
Predefinito:443
agent
Predefinito:https.globalAgent
callback
<Funzione>- Restituisce: <http.ClientRequest>
Effettua una richiesta a un server web sicuro.
Sono accettate anche le seguenti options
aggiuntive da tls.connect()
: ca
, cert
, ciphers
, clientCertEngine
(deprecato), crl
, dhparam
, ecdhCurve
, honorCipherOrder
, key
, passphrase
, pfx
, rejectUnauthorized
, secureOptions
, secureProtocol
, servername
, sessionIdContext
, highWaterMark
.
options
può essere un oggetto, una stringa o un oggetto URL
. Se options
è una stringa, viene analizzata automaticamente con new URL()
. Se è un oggetto URL
, verrà automaticamente convertito in un normale oggetto options
.
https.request()
restituisce un'istanza della classe http.ClientRequest
. L'istanza ClientRequest
è uno stream scrivibile. Se è necessario caricare un file con una richiesta POST, scrivere nell'oggetto 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()
Esempio di utilizzo delle opzioni da 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 => {
// ...
})
In alternativa, si può rinunciare al connection pooling non utilizzando un 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 => {
// ...
})
Esempio di utilizzo di un oggetto URL
come options
:
const options = new URL('https://abc:')
const req = https.request(options, res => {
// ...
})
Esempio di pinning sulla fingerprint del certificato o sulla chiave pubblica (simile a 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) {
// Assicurarsi che il certificato sia emesso per l'host a cui siamo connessi
const err = checkServerIdentity(host, cert)
if (err) {
return err
}
// Pin la chiave pubblica, simile al pinning HPKP pin-sha256
const pubkey256 = 'SIXvRyDmBJSgatgTQRGbInBaAK+hZOQ18UmrSwnDlK8='
if (sha256(cert.pubkey) !== pubkey256) {
const msg =
'Errore di verifica del certificato: ' +
`La chiave pubblica di '${cert.subject.CN}' ` +
'non corrisponde alla nostra fingerprint appuntata'
return new Error(msg)
}
// Pin il certificato esatto, piuttosto che la chiave pubblica
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 =
'Errore di verifica del certificato: ' +
`Il certificato di '${cert.subject.CN}' ` +
'non corrisponde alla nostra fingerprint appuntata'
return new Error(msg)
}
// Questo ciclo è solo informativo.
// Stampa il certificato e le fingerprint della chiave pubblica di tutti i certificati nella
// catena. È comune appuntare la chiave pubblica dell'emittente su internet pubblico, mentre si appunta la chiave pubblica del servizio in ambienti sensibili.
let lastprint256
do {
console.log('Subject Common Name:', cert.subject.CN)
console.log(' Certificate SHA256 fingerprint:', cert.fingerprint256)
const hash = createHash('sha256')
console.log(' Public key 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('Tutto OK. Il server corrisponde al nostro certificato o chiave pubblica appuntati')
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) {
// Assicurarsi che il certificato sia emesso per l'host a cui siamo connessi
const err = tls.checkServerIdentity(host, cert)
if (err) {
return err
}
// Pin la chiave pubblica, simile al pinning HPKP pin-sha256
const pubkey256 = 'SIXvRyDmBJSgatgTQRGbInBaAK+hZOQ18UmrSwnDlK8='
if (sha256(cert.pubkey) !== pubkey256) {
const msg =
'Errore di verifica del certificato: ' +
`La chiave pubblica di '${cert.subject.CN}' ` +
'non corrisponde alla nostra fingerprint appuntata'
return new Error(msg)
}
// Pin il certificato esatto, piuttosto che la chiave pubblica
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 =
'Errore di verifica del certificato: ' +
`Il certificato di '${cert.subject.CN}' ` +
'non corrisponde alla nostra fingerprint appuntata'
return new Error(msg)
}
// Questo ciclo è solo informativo.
// Stampa il certificato e le fingerprint della chiave pubblica di tutti i certificati nella
// catena. È comune appuntare la chiave pubblica dell'emittente su internet pubblico, mentre si appunta la chiave pubblica del servizio in ambienti sensibili.
do {
console.log('Subject Common Name:', cert.subject.CN)
console.log(' Certificate SHA256 fingerprint:', cert.fingerprint256)
hash = crypto.createHash('sha256')
console.log(' Public key 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('Tutto OK. Il server corrisponde al nostro certificato o chiave pubblica appuntati')
console.log('statusCode:', res.statusCode)
res.on('data', d => {})
})
req.on('error', e => {
console.error(e.message)
})
req.end()
Output ad esempio:
Subject Common Name: github.com
Certificate SHA256 fingerprint: 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
Public key ping-sha256: SIXvRyDmBJSgatgTQRGbInBaAK+hZOQ18UmrSwnDlK8=
Subject Common Name: Sectigo ECC Domain Validation Secure Server CA
Certificate SHA256 fingerprint: 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
Public key ping-sha256: Eep0p/AsSa9lFUH6KT2UY+9s1Z8v7voAPkQ4fGknZ2g=
Subject Common Name: USERTrust ECC Certification Authority
Certificate SHA256 fingerprint: 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
Public key ping-sha256: UJM2FOhG9aTNY0Pg4hgqjNzZ/lQBiMGRxPD5Y2/e0bw=
Subject Common Name: AAA Certificate Services
Certificate SHA256 fingerprint: 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
Public key ping-sha256: vRU+17BDT2iGsXvOi76E7TQMcTLXAqj0+jGPdW7L1vM=
Tutto OK. Il server corrisponde al nostro certificato o chiave pubblica appuntati
statusCode: 200