Compartilhar via


Associações de entrada do Azure Web PubSub para o Azure Functions

Nossa extensão fornece duas associação de entrada que se direcionam a necessidades diferentes.

  • WebPubSubConnection

    Para permitir que um cliente se conecte ao serviço Azure Web PubSub, ele deve saber o ponto de extremidade de serviço e ter um token de acesso válido. A associação de entrada WebPubSubConnection produz informações necessárias para que o cliente não precise lidar com a geração de token em si. O token é limitado no tempo e pode autenticar um usuário específico em uma conexão. Portanto, não armazene o token em cache nem o compartilhe entre clientes. Um gatilho HTTP que funciona com essa associação de entrada pode ser usado para que os clientes recuperem as informações de conexão.

  • WebPubSubContext

    Ao usar aplicativos Web estáticos, HttpTrigger é o único gatilho com suporte. Em cenários do Web PubSub, a WebPubSubContext associação de entrada ajuda os usuários a desserializar solicitações HTTP upstream do serviço em protocolos Web PubSub. Portanto, os clientes podem obter resultados semelhantes em comparação com WebPubSubTrigger para facilmente lidar com as funções. Quando usado com HttpTrigger, o cliente requer a configuração adequada da URL exposta do HttpTrigger no manipulador de eventos.

WebPubSubConnection

Exemplo

O exemplo a seguir mostra uma função de gatilho HTTP que adquire informações de conexão do Web PubSub usando a associação de entrada e as retorna por HTTP. No exemplo a seguir, o é passado por meio da parte de consulta de solicitação do cliente, UserId como ?userid={User-A}.

[Function("WebPubSubConnectionInputBinding")]
public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequestData req,
[WebPubSubConnectionInput(Hub = "<hub>", , UserId = "{query.userid}", Connection = "<web_pubsub_connection_name>")] WebPubSubConnection connectionInfo)
{
    var response = req.CreateResponse(HttpStatusCode.OK);
    response.WriteAsJsonAsync(connectionInfo);
    return response;
}
const { app, input } = require('@azure/functions');

const connection = input.generic({
    type: 'webPubSubConnection',
    name: 'connection',
    userId: '{query.userId}',
    hub: '<hub>'
});

app.http('negotiate', {
    methods: ['GET', 'POST'],
    authLevel: 'anonymous',
    extraInputs: [connection],
    handler: async (request, context) => {
        return { body: JSON.stringify(context.extraInputs.get('connection')) };
    },
});

Crie uma pasta negocie e atualize negociar/function.json e copie os seguintes códigos JSON.

{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    },
    {
      "type": "webPubSubConnection",
      "name": "connection",
      "userId": "{query.userid}",
      "hub": "<hub>",
      "direction": "in"
    }
  ]
}

Defina a função em negociar/inicializar.py.

import logging

import azure.functions as func

def main(req: func.HttpRequest, connection) -> func.HttpResponse:
    return func.HttpResponse(connection)

Observação

Amostras completas para este idioma estão pendentes

Observação

As extensões Web PubSub para Java ainda não são suportadas.

Obter ID de usuário autenticado

Se a função for disparada por um cliente autenticado, você poderá adicionar uma declaração de ID de usuário ao token gerado. Você pode adicionar facilmente a autenticação a um aplicativo de funções usando Autenticação de Serviço de Aplicativo.

Autenticação do Serviço de Aplicativo define os cabeçalhos HTTP denominados x-ms-client-principal-id e x-ms-client-principal-name que contêm a ID e o nome da entidade de segurança do cliente do usuário autenticado, respectivamente.

Você pode definir a UserId propriedade da associação como o valor de qualquer cabeçalho usando uma expressão de associação: {headers.x-ms-client-principal-id} ou {headers.x-ms-client-principal-name}.

[Function("WebPubSubConnectionInputBinding")]
public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequestData req,
[WebPubSubConnectionInput(Hub = "<hub>", , UserId = "{headers.x-ms-client-principal-id}", Connection = "<web_pubsub_connection_name>")] WebPubSubConnection connectionInfo)
{
    var response = req.CreateResponse(HttpStatusCode.OK);
    response.WriteAsJsonAsync(connectionInfo);
    return response;
}
const { app, input } = require('@azure/functions');

const connection = input.generic({
    type: 'webPubSubConnection',
    name: 'connection',
    userId: '{headers.x-ms-client-principal-id}',
    hub: '<hub>'
});

app.http('negotiate', {
    methods: ['GET', 'POST'],
    authLevel: 'anonymous',
    extraInputs: [connection],
    handler: async (request, context) => {
        return { body: JSON.stringify(context.extraInputs.get('connection')) };
    },
});

Crie uma pasta negocie e atualize negociar/function.json e copie os seguintes códigos JSON.

{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    },
    {
      "type": "webPubSubConnection",
      "name": "connection",
      "userId": "{headers.x-ms-client-principal-id}",
      "hub": "<hub>",
      "direction": "in"
    }
  ]
}

Defina a função em negociar/inicializar.py.

import logging

import azure.functions as func

def main(req: func.HttpRequest, connection) -> func.HttpResponse:
    return func.HttpResponse(connection)

Observação

Amostras completas para este idioma estão pendentes

Observação

As extensões Web PubSub para Java ainda não são suportadas.

Configuração

A tabela a seguir explica as propriedades de configuração de associação que você define no arquivo function.json e no atributo WebPubSubConnection.

Propriedade function.json Propriedade de atributo Descrição
tipo N/D Precisa ser definida como webPubSubConnection
direção N/D Precisa ser definida como in
nome N/D Nome da variável usada no código de função para o objeto de associação de conexão de entrada.
hub Núcleo Obrigatório - o valor deve ser definido como o nome do hub do Web PubSub para que a função seja acionada. Damos suporte para definir o valor no atributo como prioridade mais alta ou pode ser definido nas configurações do aplicativo como um valor global.
userId ID do Usuário Opcional – o valor da declaração do identificador de usuário a ser definida no token de chave de acesso.
protocolo de cliente ClientProtocol Opcional - O tipo de protocolo do cliente. Os valores válidos incluem default e mqtt.
Para clientes MQTT, você deve configurá-lo como mqtt.
Para outros clientes, você pode omitir a propriedade ou defini-la como default.
conexão Conexão Obrigatório - o nome da configuração do aplicativo que contém a cadeia de conexão do Serviço do Web PubSub (o padrão é "WebPubSubConnectionString").

Uso

WebPubSubConnection fornece as seguintes propriedades.

Nome da associação Tipo de associação Descrição
BaseUri URI URL de conexão de cliente do Web PubSub.
URI URI O URI absoluto da conexão Web PubSub contém a base gerada AccessToken na solicitação.
AccessToken cadeia Gerado AccessToken com base na solicitação do UserId e informações de serviço.

WebPubSubConnection fornece as seguintes propriedades.

Nome da associação Descrição
baseUrl URL de conexão de cliente do Web PubSub.
URL O URI absoluto da conexão Web PubSub contém a base gerada AccessToken na solicitação.
accessToken Gerado AccessToken com base na solicitação do UserId e informações de serviço.

Observação

As extensões Web PubSub para Java ainda não são suportadas.

Mais personalização do token gerado

Limitado aos tipos de parâmetro de associação que não dão suporte a uma maneira de passar lista nem matriz, o WebPubSubConnection não é totalmente compatível com todos os parâmetros que o SDK do servidor tem, especialmente roles, e também inclui groups e expiresAfter.

Quando o cliente precisar adicionar funções ou atrasar a criação do token de acesso na função, sugerimos que você trabalhe com o SDK do servidor para C#.

[Function("WebPubSubConnectionCustomRoles")]
public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequestData req)
{
    var serviceClient = new WebPubSubServiceClient(new Uri(endpoint), "<hub>", "<web-pubsub-connection-string>");
    var userId = req.Query["userid"].FirstOrDefault();
    // your method to get custom roles.
    var roles = GetRoles(userId);
    var url = await serviceClient.GetClientAccessUriAsync(TimeSpan.FromMinutes(5), userId, roles);
    var response = req.CreateResponse(HttpStatusCode.OK);
    response.WriteString(url.ToString());
    return response;
}

Quando o cliente precisar adicionar funções ou atrasar a criação do token de acesso na função, sugerimos que você trabalhe com o SDK do servidor para JavaScript.

const { app } = require('@azure/functions');
const { WebPubSubServiceClient } = require('@azure/web-pubsub');
app.http('negotiate', {
    methods: ['GET', 'POST'],
    authLevel: 'anonymous',
    handler: async (request, context) => {
        const serviceClient = new WebPubSubServiceClient(process.env.WebPubSubConnectionString, "<hub>");
        let token = await serviceClient.getAuthenticationToken({ userId: req.query.userid, roles: ["webpubsub.joinLeaveGroup", "webpubsub.sendToGroup"] });
        return { body: token.url };
    },
});

Observação

Amostras completas para este idioma estão pendentes

Observação

As extensões Web PubSub para Java ainda não são suportadas.

WebPubSubContext

Exemplo

// validate method when upstream set as http://<func-host>/api/{event}
[Function("validate")]
public static HttpResponseData Validate(
    [HttpTrigger(AuthorizationLevel.Anonymous, "options")] HttpRequestData req,
    [WebPubSubContextInput] WebPubSubContext wpsReq)
{
    return BuildHttpResponseData(req, wpsReq.Response);
}

// Respond AbuseProtection to put header correctly.
private static HttpResponseData BuildHttpResponseData(HttpRequestData request, SimpleResponse wpsResponse)
{
    var response = request.CreateResponse();
    response.StatusCode = (HttpStatusCode)wpsResponse.Status;
    response.Body = response.Body;
    foreach (var header in wpsResponse.Headers)
    {
        response.Headers.Add(header.Key, header.Value);
    }
    return response;
}
const { app, input } = require('@azure/functions');

const wpsContext = input.generic({
    type: 'webPubSubContext',
    name: 'wpsContext'
});

app.http('connect', {
    methods: ['GET', 'POST'],
    authLevel: 'anonymous',
    extraInputs: [wpsContext],
    handler: async (request, context) => {
        var wpsRequest = context.extraInputs.get('wpsContext');

        return { "userId": wpsRequest.request.connectionContext.userId };
    }
});

Observação

Amostras completas para este idioma estão pendentes

Observação

As extensões Web PubSub para Java ainda não são suportadas.

Configuração

A tabela a seguir explica as propriedades de configuração de associação que você define no arquivo functions.json e no atributo WebPubSubContext.

Propriedade function.json Propriedade de atributo Descrição
tipo N/D Deve ser definido como webPubSubContext.
direção N/D Deve ser definido como in.
nome N/D Nome da variável usada no código de função para a solicitação Web PubSub de entrada.
conexão Conexão Opcional - o nome de uma coleção de configurações de aplicativo ou de configuração que especifica o serviço do Azure Web PubSub upstream. O valor é usado para Proteção contra abuso e Validação de assinatura. O valor é resolvido automaticamente com "WebPubSubConnectionString" por padrão. E null significa que a validação não é necessária e sempre é bem-sucedida.

Importante

Para obter a segurança ideal, seu aplicativo de funções deve usar identidades gerenciadas ao se conectar ao serviço Web PubSub em vez de usar uma cadeia de conexão, que contém uma chave secreta compartilhada. Para obter mais informações, consulte Autorizar uma solicitação de identidade gerenciada usando a ID do Microsoft Entra.

Uso

WebPubSubContext fornece as seguintes propriedades.

Nome da associação Tipo de associação Descrição Propriedades
solicitação WebPubSubEventRequest Solicitação do cliente, consulte a tabela a seguir para obter detalhes. WebPubSubConnectionContext do cabeçalho de solicitação e outras propriedades desserializadas do corpo da solicitação descrevem a solicitação, por exemplo, Reason para \DisconnectedEventRequest.
resposta HttpResponseMessage A extensão cria a resposta principalmente para AbuseProtection e casos de erros. -
mensagem de erro cadeia Descreve os detalhes do erro ao processar a solicitação de upstream. -
hasError Bool Sinalizador para indicar se é uma solicitação de upstream do Web PubSub válida. -
isPreflight Bool Sinalizador para indicar se é uma solicitação de simulação de AbuseProtection. -

Em WebPubSubEventRequest, ela é desserializada para classes diferentes que fornecem informações diferentes sobre o cenário de solicitação. Em PreflightRequest ou casos inválidos, o usuário pode verificar os sinalizadores IsPreflight e HasError para saber. Sugerimos que você retorne a resposta WebPubSubContext.Response de compilação do sistema diretamente, ou o cliente pode registrar erros sob demanda. Em diferentes cenários, o cliente pode ler as propriedades da solicitação da seguinte maneira.

Classe Derivada Descrição Propriedades
PreflightRequest Usado em AbuseProtection quando IsPreflight for true -
ConnectEventRequest Usado no tipo de evento do sistema Connect Declarações, Consulta, Subprotocols, ClientCertificates
ConnectedEventRequest Usado no tipo de evento do sistema Connected -
UserEventRequest Usado no tipo de evento de usuário Dados, DataType
DisconnectedEventRequest Usado no tipo de evento do sistema Disconnected Motivo

Observação

Embora a WebPubSubContext é uma associação de entrada fornece uma desserialização de solicitação semelhante em HttpTrigger comparação com WebPubSubTrigger, há limitações, ou seja, o estado da conexão após a mesclagem não é suportado. A resposta de retorno ainda é respeitada pelo lado do serviço, mas os usuários precisam criar a resposta por conta própria. Se os usuários precisam definir a resposta do evento, você deve retornar um HttpResponseMessage contém ConnectEventResponse ou mensagens do evento de usuário como corpo da resposta e colocar o estado da conexão com a chave ce-connectionstate no cabeçalho de resposta.