Tutorial: autenticação do Azure SignalR Service com as Funções do Azure Functions

Neste tutorial passo a passo, você cria uma sala de chat com autenticação e mensagens privadas usando estas tecnologias:

  • Azure Functions: API de back-end para autenticar usuários e enviar mensagens de bate-papo.
  • Serviço Azure SignalR: Serviço para transmitir novas mensagens para clientes de chat conectados.
  • Armazenamento do Azure: serviço de armazenamento que o Azure Functions exige.
  • Serviço de Aplicativo do Azure: Serviço que fornece autenticação de usuário.

Nota

Você pode obter o código mencionado neste artigo do GitHub.

Pré-requisitos

Tem problemas? Deixe-nos saber.

Criar recursos essenciais no Azure

Criar um recurso do Serviço Azure SignalR

Seu aplicativo acessará uma instância do Serviço Azure SignalR. Use as seguintes etapas para criar uma instância do Serviço Azure SignalR usando o portal do Azure:

  1. No portal do Azure, selecione o botão Criar um recurso (+).

  2. Procure SignalR Service e selecione-o.

  3. Selecione Criar.

  4. Introduza as seguintes informações.

    Nome Valor
    Grupo de recursos Crie um novo grupo de recursos com um nome exclusivo.
    Nome do recurso Insira um nome exclusivo para a instância do Serviço Azure SignalR.
    Região Selecione uma região perto de si.
    Escalão de Preço Selecione Gratuito.
    Modo de serviço Selecione Sem servidor.
  5. Selecione Rever + Criar.

  6. Selecione Criar.

Tem problemas? Deixe-nos saber.

Criar um aplicativo de função do Azure e uma conta de armazenamento do Azure

  1. Na home page no portal do Azure, selecione Criar um recurso (+).

  2. Procure por Function App e selecione-o.

  3. Selecione Criar.

  4. Introduza as seguintes informações.

    Nome Valor
    Grupo de recursos Use o mesmo grupo de recursos com sua instância do Serviço Azure SignalR.
    Nome da Aplicação de Funções Insira um nome exclusivo para o aplicativo de função.
    Pilha de runtime selecione Node.js.
    Região Selecione uma região perto de si.
  5. Por padrão, uma nova conta de armazenamento do Azure é criada no mesmo grupo de recursos junto com seu aplicativo de função. Se você quiser usar outra conta de armazenamento no aplicativo de função, alterne para a guia Hospedagem para escolher uma conta.

  6. Selecione Rever + Criar e, em seguida, selecione Criar.

Criar um projeto do Azure Functions localmente

Inicializar um aplicativo de função

  1. A partir de uma linha de comando, crie uma pasta raiz para o seu projeto e mude para a pasta.

  2. Execute o seguinte comando no seu terminal para criar um novo projeto JavaScript Functions:

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

Por padrão, o projeto gerado inclui um arquivo host.json que contém os pacotes de extensão que incluem a extensão SignalR. Para obter mais informações sobre pacotes de extensão, consulte Registrar extensões de vinculação do Azure Functions.

Configurar definições da aplicação

Quando você executa e depura o tempo de execução do Azure Functions localmente, o aplicativo de função lê as configurações do aplicativo do local.settings.json. Atualize esse arquivo com as cadeias de conexão da instância do Serviço SignalR do Azure e a conta de armazenamento que você criou anteriormente.

Substitua o conteúdo do local.settings.json pelo seguinte código:

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

No código anterior:

  • Insira a cadeia de conexão do Serviço Azure SignalR na AzureSignalRConnectionString configuração.

    Para obter a cadeia de caracteres, vá para sua instância do Serviço Azure SignalR no portal do Azure. Na seção Configurações, localize a configuração Chaves. Selecione o botão Copiar à direita da cadeia de conexão para copiá-lo para a área de transferência. Você pode usar a cadeia de conexão primária ou secundária.

  • Insira a cadeia de conexão da conta de armazenamento na AzureWebJobsStorage configuração.

    Para obter a cadeia de caracteres, vá para sua conta de armazenamento no portal do Azure. Na seção Segurança + rede, localize a configuração Teclas de acesso. Selecione o botão Copiar à direita da cadeia de conexão para copiá-lo para a área de transferência. Você pode usar a cadeia de conexão primária ou secundária.

Tem problemas? Deixe-nos saber.

Criar uma função para autenticar usuários no Serviço Azure SignalR

Quando a aplicação de chat é aberta pela primeira vez no browser, requer credenciais de ligação válidas para ligar ao Azure SignalR Service. Crie uma função de gatilho HTTP nomeada negotiate em seu aplicativo de função para retornar essas informações de conexão.

Nota

Esta função deve ser nomeada negotiate porque o cliente SignalR requer um ponto de extremidade que termina em /negotiate.

  1. Na pasta raiz do projeto, crie a função a negotiate partir de um modelo interno usando o seguinte comando:

    func new --template "HTTP trigger" --name negotiate
    
  2. Abra src/functions/negotiate.js, atualize o conteúdo da seguinte forma:

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

    A função contém uma ligação de gatilho HTTP para receber solicitações de clientes SignalR. A função também contém uma ligação de entrada SignalR para gerar credenciais válidas para um cliente se conectar a um hub do Serviço Azure SignalR chamado default.

    Esta função obtém as informações de conexão SignalR da ligação de entrada e as retorna ao cliente no corpo da resposta HTTP..

    Não há nenhuma userId propriedade na vinculação para o signalRConnectionInfo desenvolvimento local. Você irá adicioná-lo mais tarde para definir o nome de usuário de uma conexão SignalR quando implantar o aplicativo de função no Azure.

Tem problemas? Deixe-nos saber.

Criar uma função para enviar mensagens de chat

A aplicação Web também requer uma API HTTP para enviar mensagens de chat. Crie uma função de gatilho HTTP que envia mensagens para todos os clientes conectados que usam o Serviço Azure SignalR:

  1. Na pasta raiz do projeto, crie uma função de gatilho HTTP nomeada sendMessage a partir do modelo usando o seguinte comando:

    func new --name sendMessage --template "Http trigger"
    
  2. Abra o arquivo src/functions/sendMessage.js , atualize o conteúdo da seguinte maneira:

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

    A função contém um gatilho HTTP e uma ligação de saída SignalR. Ele pega o corpo da solicitação HTTP e o envia para clientes conectados ao Serviço Azure SignalR. Ele invoca uma função nomeada newMessage em cada cliente.

    A função pode ler a identidade do remetente e pode aceitar um recipient valor no corpo da mensagem para permitir que você envie uma mensagem de forma privada para um único usuário. Você usará essas funcionalidades mais adiante no tutorial.

  3. Guarde o ficheiro.

Tem problemas? Deixe-nos saber.

Hospede a interface do usuário da Web do cliente de bate-papo

A interface do usuário do aplicativo de bate-papo é um aplicativo simples de página única (SPA) criado com a estrutura JavaScript Vue usando o cliente JavaScript ASP.NET Core SignalR. Para simplificar, o aplicativo de função hospeda a página da Web. Em um ambiente de produção, você pode usar aplicativos Web estáticos para hospedar a página da Web.

  1. Crie um arquivo chamado index.html no diretório raiz do seu projeto de função.

  2. Copie e cole o conteúdo do index.html no seu ficheiro. Guarde o ficheiro.

  3. Na pasta raiz do projeto, crie uma função de gatilho HTTP nomeada index a partir do modelo usando este comando:

    func new --name index --template "Http trigger"
    
  4. Modifique o conteúdo de src/functions/index.js para o seguinte código:

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

    A função lê a página da Web estática e a retorna ao usuário.

  5. Teste seu aplicativo localmente. Inicie o aplicativo de função usando este comando:

    func start
    
  6. Abra http://localhost:7071/api/index no seu navegador da Web. Deve aparecer uma página Web de chat.

    Captura de ecrã de uma interface de utilizador Web para um cliente de chat local.

  7. Insira uma mensagem na caixa de chat.

    Depois de selecionar a tecla Enter, a mensagem aparece na página da Web. Como o nome de usuário do cliente SignalR não está definido, você está enviando todas as mensagens anonimamente.

Tem problemas? Deixe-nos saber.

Implementar no Azure e ativar a autenticação

Você tem executado o aplicativo de função e o aplicativo de bate-papo localmente. Agora, implante-os no Azure e habilite a autenticação e as mensagens privadas.

Configurar o aplicativo de função para autenticação

Até agora, a aplicação de chat funciona anonimamente. No Azure, você usará a autenticação do Serviço de Aplicativo para autenticar o usuário. O ID de usuário ou nome de usuário do usuário autenticado é passado para a SignalRConnectionInfo associação para gerar informações de conexão autenticadas como o usuário.

  1. Abra o arquivo src/functions/negotiate.js .

  2. Insira uma userId propriedade na inputSignalR associação com o valor {headers.x-ms-client-principal-name}. Esse valor é uma expressão de associação que define o nome de usuário do cliente SignalR como o nome do usuário autenticado. A vinculação agora deve se parecer com este exemplo:

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

Implantar o aplicativo de função no Azure

Implante o aplicativo de função no Azure usando o seguinte comando:

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

A --publish-local-settings opção publica suas configurações locais do arquivo local.settings.json no Azure, para que você não precise configurá-las no Azure novamente.

Ativar a autenticação do Serviço de Aplicações

O Azure Functions suporta autenticação com Microsoft Entra ID, Facebook, Twitter, conta Microsoft e Google. Você usará a Microsoft como o provedor de identidade para este tutorial.

  1. No portal do Azure, vá para a página de recursos do seu aplicativo de função.

  2. Selecione Autenticação de configurações>.

  3. Selecione Adicionar provedor de identidade.

    Captura de tela da página Autenticação do aplicativo de função e do botão para adicionar um provedor de identidade.

  4. Na lista Provedor de identidade , selecione Microsoft. Em seguida, selecione Adicionar.

    Captura de tela da página para adicionar um provedor de identidade.

As configurações concluídas criam um registro de aplicativo que associa seu provedor de identidade ao seu aplicativo de função.

Para obter mais informações sobre os provedores de identidade suportados, consulte os seguintes artigos:

Experimentar a aplicação

  1. Abrir https://<YOUR-FUNCTION-APP-NAME>.azurewebsites.net/api/index.
  2. Selecione Iniciar sessão para autenticar com o fornecedor de autenticação selecionado.
  3. Envie mensagens públicas inserindo-as na caixa de chat principal.
  4. Envie mensagens privadas selecionando um nome de usuário no histórico de bate-papo. Apenas o destinatário selecionado recebe essas mensagens.

Captura de ecrã de uma aplicação de chat de cliente online autenticada.

Parabéns! Você implantou um aplicativo de bate-papo sem servidor em tempo real.

Tem problemas? Deixe-nos saber.

Clean up resources (Limpar recursos)

Para limpar os recursos que você criou neste tutorial, exclua o grupo de recursos usando o portal do Azure.

Atenção

A exclusão do grupo de recursos exclui todos os recursos que ele contém. Se o grupo de recursos contiver recursos fora do escopo deste tutorial, eles também serão excluídos.

Tem problemas? Deixe-nos saber.

Próximos passos

Neste tutorial, aprendeu a utilizar as Funções do Azure com o Azure SignalR Service. Leia mais sobre como criar aplicativos sem servidor em tempo real com associações do Serviço Azure SignalR para o Azure Functions:

Tem problemas? Deixe-nos saber.