Condividi tramite


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:

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

Problemi? Segnalarli.

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:

  1. Nel portale di Azure, selezionare il pulsante Crea una risorsa (+).

  2. Cercare il servizio SignalR e selezionarlo.

  3. Seleziona Crea.

  4. 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.
  5. Selezionare Rivedi e crea.

  6. Seleziona Crea.

Problemi? Segnalarli.

Creare un'app per le funzioni di Azure e un account di archiviazione di Azure

  1. Nella home page del portale di Azure, selezionare Crea una risorsa (+).

  2. Cercare App per le funzioni e selezionarla.

  3. Seleziona Crea.

  4. 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.
  5. 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.

  6. Selezionare Rivedi e crea e quindi Crea.

Creare un progetto di Funzioni di Azure a livello locale

Inizializzare un'app per le funzioni

  1. Da una riga di comando creare una cartella radice per il progetto e andare alla cartella.

  2. 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.

Problemi? Segnalarli.

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.

  1. Nella cartella del progetto radice creare la funzione negotiate da un modello predefinito usando il comando seguente:

    func new --template "HTTP trigger" --name negotiate
    
  2. 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 binding signalRConnectionInfo 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.

Problemi? Segnalarli.

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:

  1. 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"
    
  2. 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.

  3. Salvare il file.

Problemi? Segnalarli.

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.

  1. Creare un file denominato index.html nella directory radice del progetto di funzione.

  2. Copiare e incollare il contenuto di index.html nel file. Salvare il file.

  3. 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"
    
  4. 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.

  5. Testare l'app in locale. Avviare l'app per le funzioni usando questo comando:

    func start
    
  6. Aprire http://localhost:7071/api/index nel Web browser. Verrà visualizzata una pagina Web di chat.

    Screenshot di un'interfaccia utente Web per un client di chat locale.

  7. 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.

Problemi? Segnalarli.

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.

  1. Aprire il file src/functions/negotiate.js.

  2. Inserire una proprietà userId nel binding inputSignalR 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}'
    });
    
  3. 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à.

  1. Nel portale di Azure andare alla pagina delle risorse dell'app per le funzioni.

  2. Selezionare Impostazioni>Autenticazione.

  3. Fare clic su Aggiungi provider di identità.

    Screenshot della pagina Autenticazione dell'app per le funzioni e del pulsante per l'aggiunta di un provider di identità.

  4. Nell'elenco Provider di identità selezionare Microsoft. Selezionare Aggiungi.

    Screenshot della pagina per l'aggiunta di un provider di identità.

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

  1. https://<YOUR-FUNCTION-APP-NAME>.azurewebsites.net/api/index aperti.
  2. Selezionare Accesso per eseguire l'autenticazione con il provider di autenticazione scelto.
  3. Inviare messaggi pubblici digitandoli nella casella di chat principale.
  4. Inviare messaggi privati selezionando un nome utente nella cronologia delle chat. Solo il destinatario selezionato riceve questi messaggi.

Screenshot di un'app di chat client online autenticata.

Complimenti. È stata distribuita un'app di chat serverless in tempo reale.

Problemi? Segnalarli.

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.

Problemi? Segnalarli.

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:

Problemi? Segnalarli.