Esercitazione: Autenticazione del servizio Azure SignalR con Funzioni di Azure
In questa esercitazione dettagliata si creerà una chat room con autenticazione e messaggistica privata usando queste tecnologie:
- Funzioni di Azure: API di back-end per l'autenticazione degli utenti e l'invio di messaggi di chat.
- Servizio Azure SignalR: servizio per la trasmissione di nuovi messaggi ai client di chat connessi.
- Archiviazione di Azure: servizio di archiviazione richiesto da Funzioni di Azure.
- Servizio app di Azure: servizio che fornisce l'autenticazione utente.
Nota
È possibile ottenere il codice menzionato in questo articolo da GitHub.
Importante
Le stringa di connessione non elaborate vengono visualizzate in questo articolo solo a scopo dimostrativo.
Una stringa di connessione include le informazioni sull'autorizzazione necessarie all'applicazione per l'accesso al servizio Azure Web PubSub. La chiave di accesso all'interno della stringa di connessione è simile a una password radice per il servizio. Negli ambienti di produzione proteggere sempre le chiavi di accesso. Usare Azure Key Vault per gestire e ruotare le chiavi in modo sicuro e proteggere i stringa di connessione usando Microsoft Entra ID e autorizzare l'accesso con Microsoft Entra ID.
Evitare di distribuire le chiavi di accesso ad altri utenti, impostarle come hardcoded o salvarle in un file di testo normale accessibile ad altri. Ruotare le chiavi se si ritiene che siano state compromesse.
Prerequisiti
- Un account Azure con una sottoscrizione attiva. Se non hai un account, puoi crearlo gratuitamente.
- Node.js (versione 20.x).
- Strumenti di base di Funzioni di Azure (versione 4).
Creare risorse essenziali in Azure
Creare una risorsa servizio Azure SignalR
L'applicazione accederà a un'istanza del servizio Azure SignalR. Usare la procedura seguente per creare un'istanza del servizio Azure SignalR usando il portale di Azure:
Nel portale di Azure, selezionare il pulsante Crea una risorsa (+).
Cercare il servizio SignalR e selezionarlo.
Seleziona Crea.
Immetti le informazioni seguenti.
Nome Valore Gruppo di risorse Creare un nuovo gruppo di risorse con un nome univoco. Nome risorsa Immettere un nome univoco per l'istanza del servizio Azure SignalR. Area Selezionare un'area nelle vicinanze. Piano tariffario Selezionare Gratuito. Modalità di servizio Selezionare Serverless. Selezionare Rivedi e crea.
Seleziona Crea.
Creare un'app per le funzioni di Azure e un account di archiviazione di Azure
Nella home page del portale di Azure, selezionare Crea una risorsa (+).
Cercare App per le funzioni e selezionarla.
Seleziona Crea.
Immetti le informazioni seguenti.
Nome Valore Gruppo di risorse Usare lo stesso gruppo di risorse con l'istanza del servizio Azure SignalR. Nome dell'app per le funzioni Immettere un nome univoco per l'app per le funzioni. Stack di runtime selezionare Node.js. Area Selezionare un'area nelle vicinanze. Per impostazione predefinita, viene creato un nuovo account di archiviazione di Azure nello stesso gruppo di risorse insieme all'app per le funzioni. Se si desidera usare un altro account di archiviazione nell'app per le funzioni, andare alla scheda Hosting per scegliere un account.
Selezionare Rivedi e crea e quindi Crea.
Creare un progetto di Funzioni di Azure a livello locale
Inizializzare un'app per le funzioni
Da una riga di comando creare una cartella radice per il progetto e andare alla cartella.
Eseguire il comando seguente nel terminale per creare un nuovo progetto funzioni JavaScript:
func init --worker-runtime node --language javascript --name my-app --model V4
Per impostazione predefinita, il progetto generato include un file host.json che contiene i bundle di estensioni che includono l'estensione SignalR. Per altre informazioni sui bundle di estensioni, vedere Registrare le estensioni di binding di Funzioni di Azure.
Configurare le impostazioni dell'applicazione
Quando si esegue e si sottopone a debug il runtime di Funzioni di Azure in locale, l'app per le funzioni legge le impostazioni dell'applicazione da local.settings.json. Aggiornare questo file con le stringhe di connessione dell'istanza del servizio Azure SignalR e l'account di archiviazione creato in precedenza.
Le stringa di connessione non elaborate vengono visualizzate in questo articolo solo a scopo dimostrativo. Negli ambienti di produzione proteggere sempre le chiavi di accesso. Usare Azure Key Vault per gestire e ruotare le chiavi in modo sicuro e proteggere i stringa di connessione usando Microsoft Entra ID e autorizzare l'accesso con Microsoft Entra ID.
Sostituire il contenuto di local.settings.json con il codice seguente:
{
"IsEncrypted": false,
"Values": {
"FUNCTIONS_WORKER_RUNTIME": "node",
"AzureWebJobsStorage": "<your-storage-account-connection-string>",
"AzureSignalRConnectionString": "<your-Azure-SignalR-connection-string>"
}
}
Nel codice precedente:
Immettere la stringa di connessione del servizio Azure SignalR nell'impostazione
AzureSignalRConnectionString
.Per ottenere la stringa, andare all'istanza del servizio Azure SignalR nel portale di Azure. Nella sezione Impostazioni individuare l'impostazione Chiavi. Selezionare il pulsante Copia a destra della stringa di connessione per copiarlo negli Appunti. È possibile usare la stringa di connessione primaria o secondaria.
Immettere la stringa di connessione dell'account di archiviazione nell'impostazione
AzureWebJobsStorage
.Per ottenere la stringa, andare all'account di archiviazione nel portale di Azure. Nella sezione Sicurezza + networking individuare l'impostazione Chiavi di accesso. Selezionare il pulsante Copia a destra della stringa di connessione per copiarlo negli Appunti. È possibile usare la stringa di connessione primaria o secondaria.
Creare una funzione per autenticare gli utenti per il servizio Azure SignalR
Quando l'app di chat viene aperta per la prima volta nel browser, richiede credenziali di connessione valide per connettersi al servizio Azure SignalR. Creare una funzione trigger HTTP denominata negotiate
nell'app per le funzioni per restituire queste informazioni di connessione.
Nota
Questa funzione deve essere denominata negotiate
perché il client SignalR richiede un endpoint che termina con /negotiate
.
Nella cartella del progetto radice creare la funzione
negotiate
da un modello predefinito usando il comando seguente:func new --template "HTTP trigger" --name negotiate
Aprire src/functions/negotiate.js e aggiornare il contenuto nel modo seguente:
const { app, input } = require('@azure/functions'); const inputSignalR = input.generic({ type: 'signalRConnectionInfo', name: 'connectionInfo', hubName: 'default', connectionStringSetting: 'AzureSignalRConnectionString', }); app.post('negotiate', { authLevel: 'anonymous', handler: (request, context) => { return { body: JSON.stringify(context.extraInputs.get(inputSignalR)) } }, route: 'negotiate', extraInputs: [inputSignalR], });
La funzione contiene un binding di trigger HTTP per ricevere richieste dai client SignalR. La funzione contiene inoltre un binding di input SignalR che genera credenziali valide per la connessione di un client a un hub del servizio Azure SignalR denominato
default
.Questa funzione accetta le informazioni di connessione a SignalR dal binding di input e le restituisce al client nel corpo della risposta HTTP.
Non esiste alcuna
userId
proprietà nel bindingsignalRConnectionInfo
per lo sviluppo locale. Verrà aggiunto in un secondo momento per impostare il nome utente di una connessione SignalR quando si distribuisce l'app per le funzioni in Azure.
Creare una funzione per inviare messaggi di chat
L'app Web richiede anche un'API HTTP per inviare i messaggi di chat. Creare una funzione trigger HTTP che invia messaggi a tutti i client connessi che usano il servizio Azure SignalR:
Nella cartella del progetto radice creare la funzione di trigger HTTP
sendMessage
da un modello predefinito usando il comando seguente:func new --name sendMessage --template "Http trigger"
Aprire il file src/functions/sendMessage.js e aggiornare il contenuto nel modo seguente:
const { app, output } = require('@azure/functions'); const signalR = output.generic({ type: 'signalR', name: 'signalR', hubName: 'default', connectionStringSetting: 'AzureSignalRConnectionString', }); app.http('messages', { methods: ['POST'], authLevel: 'anonymous', extraOutputs: [signalR], handler: async (request, context) => { const message = await request.json(); message.sender = request.headers && request.headers.get('x-ms-client-principal-name') || ''; let recipientUserId = ''; if (message.recipient) { recipientUserId = message.recipient; message.isPrivate = true; } context.extraOutputs.set(signalR, { 'userId': recipientUserId, 'target': 'newMessage', 'arguments': [message] }); } });
La funzione contiene un trigger HTTP e un binding di output SignalR. Accetta il corpo dalla richiesta HTTP e lo invia ai client connessi al servizio Azure SignalR. Richiama una funzione denominata
newMessage
in ogni client.La funzione può leggere l'identità del mittente e può accettare un valore
recipient
nel corpo del messaggio per consentire di inviare un messaggio privatamente a un singolo utente. Queste funzionalità verranno usate più avanti nell'esercitazione.Salvare il file.
Ospitare l'interfaccia utente Web del client di chat
L'interfaccia utente dell'applicazione chat è una semplice applicazione a pagina singola creata con il framework Vue JavaScript usando il client ASP.NET Core SignalR JavaScript. Per semplicità, l'app per le funzioni ospita la pagina Web. In un ambiente di produzione è possibile usare App Web statiche per ospitare la pagina Web.
Creare un file denominato index.html nella directory radice del progetto di funzione.
Copiare e incollare il contenuto di index.html nel file. Salvare il file.
Nella cartella del progetto radice, creare una funzione di trigger HTTP denominata
index
dal modello usando questo comando:func new --name index --template "Http trigger"
Modificare il contenuto di src/functions/index.js nel codice seguente:
const { app } = require('@azure/functions'); const { readFile } = require('fs/promises'); app.http('index', { methods: ['GET'], authLevel: 'anonymous', handler: async (context) => { const content = await readFile('index.html', 'utf8', (err, data) => { if (err) { context.err(err) return } }); return { status: 200, headers: { 'Content-Type': 'text/html' }, body: content, }; } });
La funzione legge la pagina Web statica e la restituisce all'utente.
Testare l'app in locale. Avviare l'app per le funzioni usando questo comando:
func start
Aprire
http://localhost:7071/api/index
nel Web browser. Verrà visualizzata una pagina Web di chat.Immettere un messaggio nella casella di chat.
Dopo aver selezionato il tasto INVIO, il messaggio viene visualizzato nella pagina Web. Poiché il nome utente del client SignalR non è impostato, si inviano tutti i messaggi in modo anonimo.
Distribuire in Azure e abilitare l'autenticazione
L'app per le funzioni e l'app per le chat sono state eseguite in locale. Ora, distribuirli in Azure e abilitare l'autenticazione e la messaggistica privata.
Configurare l'app per le funzioni per l'autenticazione
Finora, l'app di chat ha funzionato in modo anonimo. In Azure si userà Autenticazione Servizio app per autenticare l'utente. L'ID utente o il nome utente dell'utente autenticato viene passato al binding SignalRConnectionInfo
per generare informazioni di connessione autenticate come utente.
Aprire il file src/functions/negotiate.js.
Inserire una proprietà
userId
nel bindinginputSignalR
con il valore{headers.x-ms-client-principal-name}
. Questo valore è un'espressione di binding che imposta il nome utente del client SignalR sul nome dell'utente autenticato. Il binding dovrebbe ora essere simile all'esempio seguente:const inputSignalR = input.generic({ type: 'signalRConnectionInfo', name: 'connectionInfo', hubName: 'default', connectionStringSetting: 'AzureSignalRConnectionString', userId: '{headers.x-ms-client-principal-name}' });
Salvare il file.
Distribuire l'app per le funzioni in Azure
Distribuire l'app per le funzioni in Azure usando il comando seguente:
func azure functionapp publish <your-function-app-name> --publish-local-settings
L'opzione --publish-local-settings
pubblica le impostazioni locali dal file local.settings.json in Azure, quindi non è necessario configurarle di nuovo in Azure.
Abilitare l'autenticazione del servizio app
Funzioni di Azure supporta l'autenticazione con Microsoft Entra ID, Facebook, X, account Microsoft e Google. Per questa esercitazione si userà Microsoft come provider di identità.
Nel portale di Azure andare alla pagina delle risorse dell'app per le funzioni.
Selezionare Impostazioni>Autenticazione.
Fare clic su Aggiungi provider di identità.
Nell'elenco Provider di identità selezionare Microsoft. Selezionare Aggiungi.
Le impostazioni completate creano una registrazione dell'app che associa il provider di identità all'app per le funzioni.
Per altre informazioni sui provider di identità supportati, vedere gli articoli seguenti:
Provare l'applicazione
https://<YOUR-FUNCTION-APP-NAME>.azurewebsites.net/api/index
aperti.- Selezionare Accesso per eseguire l'autenticazione con il provider di autenticazione scelto.
- Inviare messaggi pubblici digitandoli nella casella di chat principale.
- Inviare messaggi privati selezionando un nome utente nella cronologia delle chat. Solo il destinatario selezionato riceve questi messaggi.
Complimenti. È stata distribuita un'app di chat serverless in tempo reale.
Pulire le risorse
Per pulire le risorse create in questa esercitazione, eliminare il gruppo di risorse usando il portale di Azure.
Attenzione
L'eliminazione del gruppo di risorse elimina tutte le risorse contenute. Se il gruppo di risorse contiene risorse esterne all'ambito di questa esercitazione, vengono eliminate anche.
Passaggi successivi
In questa esercitazione si è appreso come usare Funzioni di Azure con il servizio Azure SignalR. Sono disponibili altre informazioni sulla creazione di applicazioni serverless in tempo reale con le associazioni del Servizio SignalR per Funzioni di Azure: