Tutorial: Azure SignalR Service-Authentifizierung mit Azure Functions

In diesem Tutorial erstellen Sie schrittweise einen Chatroom mit Authentifizierung und privatem Messaging mithilfe dieser Technologien:

  • Azure Functions: Back-End-API für das Authentifizieren von Benutzer*innen und das Senden von Chatnachrichten
  • Azure SignalR Service: Dienst zum Übertragen neuer Nachrichten an verbundene Chatclients
  • Azure Storage: Speicherdienst, den Azure Functions benötigt
  • Azure App Service: Dienst, der die Benutzerauthentifizierung bereitstellt

Hinweis

Sie finden den in diesem Artikel erwähnten Code auf GitHub.

Voraussetzungen

Treten Probleme auf? Teilen Sie es uns mit.

Erstellen wichtiger Ressourcen in Azure

Erstellen einer Azure SignalR Service-Ressource

Ihre Anwendung greift auf eine Azure SignalR Service-Instanz zu. Mit den folgenden Schritten erstellen Sie eine Azure SignalR Service-Instanz über das Azure-Portal:

  1. Wählen Sie im Azure-Portal die Schaltfläche Ressource erstellen (+) aus.

  2. Suchen Sie nach SignalR Service, und wählen Sie den Dienst aus.

  3. Klicken Sie auf Erstellen.

  4. Geben Sie Folgendes ein:

    Name Wert
    Ressourcengruppe Erstellen Sie eine neue Ressourcengruppe mit einem eindeutigen Namen.
    Ressourcenname Geben Sie einen eindeutigen Namen für die Azure SignalR Service-Instanz ein.
    Region Wählen Sie eine Region in Ihrer Nähe aus.
    Tarif Wählen Sie Free aus.
    Dienstmodus Wählen Sie Serverlos.
  5. Klicken Sie auf Überprüfen + erstellen.

  6. Klicken Sie auf Erstellen.

Treten Probleme auf? Teilen Sie es uns mit.

Erstellen einer Azure-Funktions-App und eines Azure-Speicherkontos

  1. Wählen Sie auf der Startseite des Azure-Portals die Option Ressource erstellen (+) aus.

  2. Suchen Sie nach Funktions-App, und wählen Sie diese Option aus.

  3. Klicken Sie auf Erstellen.

  4. Geben Sie Folgendes ein:

    Name Wert
    Ressourcengruppe Verwenden Sie die gleiche Ressourcengruppe wie Ihre Azure SignalR Service-Instanz.
    Name der Funktions-App Geben Sie einen eindeutigen Namen für die Funktions-App ein.
    Runtimestapel Wählen Sie Node.js aus.
    Region Wählen Sie eine Region in Ihrer Nähe aus.
  5. Standardmäßig wird zusammen mit Ihrer Funktions-App ein neues Azure-Speicherkonto in derselben Ressourcengruppe erstellt. Wenn Sie ein anderes Speicherkonto in der Funktions-App verwenden möchten, wechseln Sie zur Registerkarte Hosting, um ein Konto auszuwählen.

  6. Klicken Sie auf Review + Create (Überprüfen und erstellen) und dann auf Create (Erstellen).

Lokales Erstellen eines Azure Functions-Projekts

Initialisieren einer Funktions-App

  1. Erstellen Sie über eine Befehlszeile einen Stammordner für Ihr Projekt, und wechseln Sie zum Ordner.

  2. Führen Sie in Ihrem Terminal den folgenden Befehl aus, um ein neues Functions-Projekt mit JavaScript zu erstellen.

func init --worker-runtime node --language javascript --name my-app --model V4

Standardmäßig enthält das generierte Projekt die Datei host.json mit den Erweiterungsbundles, die die SignalR-Erweiterung enthalten. Weitere Informationen zu Erweiterungsbündeln finden Sie unter Registrieren von Bindungserweiterungen von Azure Functions.

Konfigurieren von Anwendungseinstellungen

Beim lokalen Ausführen und Debuggen der Azure Functions-Runtime liest die Funktions-App die Anwendungseinstellungen aus der Datei local.settings.json. Aktualisieren Sie diese Datei mit den Verbindungszeichenfolgen der Azure SignalR Service-Instanz und des Speicherkontos, die Sie zuvor erstellt haben.

Ersetzen Sie den Inhalt der Datei local.settings.json durch den folgenden Code:

{
  "IsEncrypted": false,
  "Values": {
    "FUNCTIONS_WORKER_RUNTIME": "node",
    "AzureWebJobsStorage": "<your-storage-account-connection-string>",
    "AzureSignalRConnectionString": "<your-Azure-SignalR-connection-string>"
  }
}

Für den Code oben gilt:

  • Geben Sie die Azure SignalR Service-Verbindungszeichenfolge als Wert für die Einstellung AzureSignalRConnectionString ein.

    Um die Zeichenfolge abzurufen, wechseln Sie im Azure-Portal zu Ihrer Azure SignalR-Dienstinstanz. Suchen Sie im Abschnitt Einstellungen die Einstellung Schlüssel. Wählen Sie rechts neben der Verbindungszeichenfolge die Schaltfläche Kopieren aus, um die Verbindungszeichenfolge in die Zwischenablage zu kopieren. Sie können die primäre oder die sekundäre Verbindungszeichenfolge verwenden.

  • Geben Sie die Verbindungszeichenfolge des Speicherkontos als Wert für die Einstellung AzureWebJobsStorage ein.

    Um die Zeichenfolge abzurufen, wechseln Sie im Azure-Portal zu Ihrem Speicherkonto. Suchen Sie im Abschnitt Sicherheit + Netzwerk die Einstellung Zugriffsschlüssel. Wählen Sie rechts neben der Verbindungszeichenfolge die Schaltfläche Kopieren aus, um die Verbindungszeichenfolge in die Zwischenablage zu kopieren. Sie können die primäre oder die sekundäre Verbindungszeichenfolge verwenden.

Treten Probleme auf? Informieren Sie uns darüber.

Erstellen einer Funktion zum Authentifizieren von Benutzer*innen bei Azure SignalR Service

Wird die Chap-App zum ersten Mal im Browser geöffnet, sind gültige Verbindungsanmeldeinformationen für das Herstellen einer Verbindung mit Azure SignalR Service erforderlich. Erstellen Sie eine HTTP-Triggerfunktion namens negotiate in Ihrer Funktions-App, um diese Verbindungsinformationen zurückzugeben.

Hinweis

Diese Funktion muss negotiate benannt werden, da der SignalR-Client einen Endpunkt erfordert, der auf /negotiateendet.

  1. Erstellen Sie mit dem folgenden Befehl im Stammordner des Projekts die Funktion negotiate aus einer integrierten Vorlage:

    func new --template "HTTP trigger" --name negotiate
    
  2. Öffnen Sie src/functions/negotiate.js, und aktualisieren Sie den Inhalt wie folgt:

    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],
    });
    

    Die Funktion enthält eine HTTP-Triggerbindung zum Empfangen von Anforderungen von SignalR-Clients. Die Funktion enthält auch eine SignalR-Eingabebindung, um gültige Anmeldeinformationen für einen Client zu generieren, damit eine Verbindung mit einem Azure SignalR Service-Hub namens default hergestellt werden kann.

    Diese Funktion übernimmt die SignalR-Verbindungsinformationen aus der Eingabebindung und gibt sie an den Client im HTTP-Antworttext zurück.

    Es gibt keine userId-Eigenschaft in der signalRConnectionInfo-Bindung für die lokale Entwicklung. Sie fügen sie später hinzu, um den Benutzernamen einer SignalR-Verbindung festzulegen, wenn Sie die Funktions-App in Azure bereitstellen.

Treten Probleme auf? Teilen Sie es uns mit.

Erstellen einer Funktion zum Senden von Chatnachrichten

Die Web-App benötigt darüber hinaus eine HTTP-API zum Senden von Chatnachrichten. Erstellen Sie eine HTTP-Triggerfunktion, die Nachrichten an alle verbundenen Clients sendet, die Azure SignalR Service verwenden:

  1. Erstellen Sie mit dem folgenden Befehl im Stammordner des Projekts eine HTTP-Triggerfunktion mit dem Namen sendMessage aus der Vorlage:

    func new --name sendMessage --template "Http trigger"
    
  2. Öffnen Sie die Datei src/functions/sendMessage.js, und aktualisieren Sie den Inhalt wie folgt:

    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]
                });
        }
    });
    

    Die Funktion enthält einen HTTP-Trigger und eine SignalR-Ausgabebindung. Sie übernimmt den Textteil aus der HTTP-Anforderung und sendet ihn an Clients, die mit Azure SignalR Service verbunden sind. Dabei wird auf jedem Client eine Funktion namens newMessage aufgerufen.

    Die Funktion kann die Identität des Absenders lesen und den Wert recipient im Nachrichtentext akzeptieren, damit Sie eine Nachricht privat an einen einzelnen Benutzer senden können. Sie verwenden diese Funktionen später im Tutorial.

  3. Speichern Sie die Datei .

Treten Probleme auf? Informieren Sie uns darüber.

Hosten der Webbenutzeroberfläche des Chatclients

Die Benutzeroberfläche der Chatanwendung ist eine einfache Single-Page-Webanwendung (Single-Page Application, SPA), die mit dem JavaScript-Framework „Vue.js“ unter Verwendung des ASP.NET Core SignalR JavaScript-Clients erstellt wurde. Der Einfachheit halber wird die Webseite von der Funktions-App gehostet. In einer Produktionsumgebung können Sie Static Web Apps zum Hosten der Webseite verwenden.

  1. Erstellen Sie eine Datei namens index.html im Stammverzeichnis Ihres Funktionsprojekts.

  2. Kopieren Sie den Inhalt der Datei index.html, und fügen Sie ihn in Ihre Datei ein. Speichern Sie die Datei .

  3. Erstellen Sie mit diesem Befehl im Stammordner des Projekts eine HTTP-Triggerfunktion mit dem Namen index aus der Vorlage:

    func new --name index --template "Http trigger"
    
  4. Ändern Sie den Inhalt der Datei src/functions/index.js, sodass sie den folgenden Code enthält:

    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,
            };
        }
    });
    

    Die Funktion liest die statische Webseite und gibt sie an den oder die Benutzer*in zurück.

  5. Testen Sie Ihre App lokal. Starten Sie die Funktions-App mit diesem Befehl:

    func start
    
  6. Öffnen Sie http://localhost:7071/api/index in Ihrem Webbrowser. Eine Chatwebseite sollte angezeigt werden.

    Screenshot: Web-Benutzeroberfläche für einen lokalen Chatclient

  7. Geben Sie eine Nachricht in das Chatfeld ein.

    Nachdem Sie die EINGABETASTE gedrückt haben, wird die Nachricht auf der Webseite angezeigt. Da der Benutzername des SignalR-Clients nicht festgelegt ist, senden Sie alle Nachrichten anonym.

Treten Probleme auf? Teilen Sie es uns mit.

Bereitstellen in Azure und Aktivieren der Authentifizierung

Sie haben die Funktions-App und die Chat-App lokal ausgeführt. Stellen Sie sie jetzt in Azure bereit, und aktivieren Sie Authentifizierung und privates Messaging.

Konfigurieren der Funktions-App für die Authentifizierung

Bisher funktioniert die Chat-App anonym. In Azure verwenden Sie die App Service-Authentifizierung für die Benutzerauthentifizierung. Die Benutzer-ID oder der Benutzername des authentifizierten Benutzers wird an die SignalRConnectionInfo-Bindung übergeben, um Verbindungsinformationen zu generieren, die als der entsprechende Benutzer authentifiziert sind.

  1. Öffnen Sie die Datei src/functions/negotiate.js.

  2. Fügen Sie eine userId-Eigenschaft in die inputSignalR-Bindung mit dem Wert {headers.x-ms-client-principal-name} ein. Dieser Wert ist ein Bindungsausdruck, der den Benutzernamen des SignalR-Clients auf den Namen des authentifizierten Benutzers festlegt. Die Bindung sollte nun wie in diesem Beispiel aussehen:

    const inputSignalR = input.generic({
        type: 'signalRConnectionInfo',
        name: 'connectionInfo',
        hubName: 'default',
        connectionStringSetting: 'AzureSignalRConnectionString',
        userId: '{headers.x-ms-client-principal-name}'
    });
    
  3. Speichern Sie die Datei .

Bereitstellen der Funktions-App in Azure

Stellen Sie die Funktions-App mit dem folgenden Befehl in Azure bereit:

func azure functionapp publish <your-function-app-name> --publish-local-settings

Die Option --publish-local-settings veröffentlicht Ihre lokalen Einstellungen aus der Datei local.settings.json in Azure, sodass Sie die Einstellungen nicht erneut in Azure konfigurieren müssen.

Aktivieren der App Service-Authentifizierung

Azure Functions unterstützt die Authentifizierung mit Microsoft Entra ID, Facebook, Twitter, Microsoft-Konten und Google. In diesem Tutorial verwenden Sie Microsoft als Identitätsanbieter.

  1. Navigieren Sie im Azure-Portal zur Ressourcenseite Ihrer Funktions-App.

  2. Wählen Sie Einstellungen>Authentifizierung aus.

  3. Wählen Sie Identitätsanbieter hinzufügen aus.

    Screenshot: Die Seite „Authentifizierung“ der Funktions-App und die Schaltfläche zum Hinzufügen eines Identitätsanbieters

  4. Wählen Sie in der Liste Identitätsanbieter den Eintrag Microsoft aus. Wählen Sie dann Hinzufügen aus.

    Screenshot: Seite zum Hinzufügen eines Identitätsanbieters

Die fertigen Einstellungen erstellen eine App-Registrierung, die Ihren Identitätsanbieter Ihrer Funktions-App zuordnet.

Weitere Informationen zu den unterstützten Identitätsanbietern finden Sie in den folgenden Artikeln:

Testen der Anwendung

  1. Öffnen Sie https://<YOUR-FUNCTION-APP-NAME>.azurewebsites.net/api/index.
  2. Wählen Sie Anmeldung aus, um sich mit dem ausgewählten Authentifizierungsanbieter zu authentifizieren.
  3. Senden Sie öffentliche Nachrichten, indem Sie sie ins Hauptchatfeld eingeben.
  4. Senden Sie private Nachrichten, indem Sie einen Benutzernamen im Chatverlauf auswählen. Nur der ausgewählte Empfänger erhält diese Nachrichten.

Screenshot: Authentifizierte Onlineclient-Chat-App

Herzlichen Glückwunsch! Sie haben eine serverlose Echtzeit-Chat-App bereitgestellt.

Treten Probleme auf? Teilen Sie es uns mit.

Bereinigen von Ressourcen

Zum Bereinigen der im Rahmen dieses Tutorials erstellten Ressourcen löschen Sie die Ressourcengruppe über das Azure-Portal.

Achtung

Beim Löschen der Ressourcengruppe werden alle darin enthaltenen Ressourcen gelöscht. Wenn die Ressourcengruppe Ressourcen enthält, die nicht zum Umfang dieses Tutorials gehören, werden diese ebenfalls gelöscht.

Treten Probleme auf? Informieren Sie uns darüber.

Nächste Schritte

In diesem Tutorial haben Sie erfahren, wie Sie Azure Functions mit Azure SignalR Service nutzen. Lesen Sie mehr über das Erstellen von serverlosen Echtzeitanwendungen mit Azure SignalR Service-Bindungen für Azure Functions.

Treten Probleme auf? Teilen Sie es uns mit.