Compartilhar via


Associação de entrada do Serviço do SignalR para o Azure Functions

Antes que um cliente possa se conectar ao serviço do Azure SignalR, ele deve recuperar a URL do ponto de extremidade de serviço e um token de acesso válido. A associação de entrada SignalRConnectionInfo produz a URL do ponto de extremidade de Serviço SignalR e um token válido que são usados para se conectar ao serviço. O token tem limite de tempo e pode ser usado para autenticar um usuário específico para uma conexão. Portanto, você não deve armazenar o token em cache ou compartilhá-lo entre clientes. Normalmente, SignalRConnectionInfo é utilizado com gatilho HTTP para os clientes recuperarem as informações de conexão.

Para obter mais informações sobre como usar essa associação para criar uma função "negotiate" compatível com um SDK do cliente SignalR, consulte Desenvolvimento e configuração do Azure Functions com o Serviço do Azure SignalR. Para obter informações sobre a instalação e detalhes de configuração, confira a visão geral.

Exemplo

A função C# pode ser criada por meio de um dos seguintes modos C#:

  • Modelo de trabalho isolado: função C# compilada executada em um processo de trabalho que está isolado do runtime. É necessário um processo de trabalho isolado para dar suporte às funções C# executadas nas versões LTS e não LTS do .NET e do .NET Framework.
  • Modelo em processo: função C# compilada no mesmo processo que o runtime do Functions.
  • Script C#: usado principalmente ao criar funções C# no portal do Azure.

O exemplo a seguir mostra uma função C# que adquire as informações de conexão do SignalR usando a associação de entrada e retorna-a via HTTP.

[Function(nameof(Negotiate))]
public static string Negotiate([HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequestData req,
    [SignalRConnectionInfoInput(HubName = "serverless")] string connectionInfo)
{
    // The serialization of the connection info object is done by the framework. It should be camel case. The SignalR client respects the camel case response only.
    return connectionInfo;
}

O exemplo a seguir mostra uma associação de entrada de informações de conexão do SignalR em um arquivo function.json e uma função que usa a associação para retornar as informações de conexão.

Aqui estão os dados de associação do exemplo no arquivo function.json:

{
    "type": "signalRConnectionInfo",
    "name": "connectionInfo",
    "hubName": "hubName1",
    "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
    "direction": "in"
}

Aqui está o código JavaScript:

const { app, input } = require('@azure/functions');

const inputSignalR = input.generic({
    type: 'signalRConnectionInfo',
    name: 'connectionInfo',
    hubName: 'hubName1',
    connectionStringSetting: 'AzureSignalRConnectionString',
});

app.post('negotiate', {
    authLevel: 'function',
    handler: (request, context) => {
        return { body: JSON.stringify(context.extraInputs.get(inputSignalR)) }
    },
    route: 'negotiate',
    extraInputs: [inputSignalR],
});

Exemplos completos do PowerShell estão pendentes.

O exemplo a seguir mostra uma associação de entrada de informações de conexão do SignalR em um arquivo function.json e uma função Python que usa a associação para retornar as informações de conexão.

Aqui está o código Python:

def main(req: func.HttpRequest, connectionInfoJson: str) -> func.HttpResponse:
    return func.HttpResponse(
        connectionInfoJson,
        status_code=200,
        headers={
            'Content-type': 'application/json'
        }
    )

O exemplo a seguir mostra uma função Java que obtém as informações de conexão do SignalR usando a associação de entrada e retorna-a por HTTP.

@FunctionName("negotiate")
public SignalRConnectionInfo negotiate(
        @HttpTrigger(
            name = "req",
            methods = { HttpMethod.POST },
            authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> req,
        @SignalRConnectionInfoInput(
            name = "connectionInfo",
            HubName = "hubName1") SignalRConnectionInfo connectionInfo) {
    return connectionInfo;
}

Aviso

Para simplificar, omitimos as partes de autenticação e autorização neste exemplo. Como resultado, esse ponto de extremidade é publicamente acessível sem nenhuma restrição. Para garantir a segurança do ponto de extremidade de negociação, você deve implementar mecanismos de autenticação e autorização apropriados com base em seus requisitos específicos. Para obter diretrizes sobre como proteger seus pontos de extremidade HTTP, consulte os seguintes artigos:

Uso

Tokens autenticados

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.

A 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 propriedade UserId da associação como o valor do cabeçalho usando uma UserId: {headers.x-ms-client-principal-id} ou {headers.x-ms-client-principal-name}.

[Function("Negotiate")]
public static string Negotiate([HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequestData req,
    [SignalRConnectionInfoInput(HubName = "hubName1", UserId = "{headers.x-ms-client-principal-id}")] string connectionInfo)
{
    // The serialization of the connection info object is done by the framework. It should be camel case. The SignalR client respects the camel case response only.
    return connectionInfo;
}
@FunctionName("negotiate")
public SignalRConnectionInfo negotiate(
        @HttpTrigger(
            name = "req",
            methods = { HttpMethod.POST, HttpMethod.GET },
            authLevel = AuthorizationLevel.ANONYMOUS)
            HttpRequestMessage<Optional<String>> req,
        @SignalRConnectionInfoInput(name = "connectionInfo", hubName = "hubName1", userId = "{headers.x-ms-signalr-userid}") SignalRConnectionInfo connectionInfo) {
    return connectionInfo;
}

Aqui estão os dados de associação no arquivo function.json:

{
    "type": "signalRConnectionInfo",
    "name": "connectionInfo",
    "hubName": "hubName1",
    "userId": "{headers.x-ms-client-principal-id}",
    "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
    "direction": "in"
}

Aqui está o código JavaScript:

const { app, input } = require('@azure/functions');

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

app.post('negotiate', {
    authLevel: 'function',
    handler: (request, context) => {
        return { body: JSON.stringify(context.extraInputs.get(inputSignalR)) }
    },
    route: 'negotiate',
    extraInputs: [inputSignalR],
});

Exemplos completos do PowerShell estão pendentes.

Aqui está o código Python:

def main(req: func.HttpRequest, connectionInfo: str) -> func.HttpResponse:
    # connectionInfo contains an access key token with a name identifier
    # claim set to the authenticated user
    return func.HttpResponse(
        connectionInfo,
        status_code=200,
        headers={
            'Content-type': 'application/json'
        }
    )
@FunctionName("negotiate")
public SignalRConnectionInfo negotiate(
        @HttpTrigger(
            name = "req",
            methods = { HttpMethod.POST },
            authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> req,
        @SignalRConnectionInfoInput(
            name = "connectionInfo",
            HubName = "hubName1",
            userId = "{headers.x-ms-client-principal-id}") SignalRConnectionInfo connectionInfo) {
    return connectionInfo;
}

Atributos

As bibliotecas C# em processo e de processo de trabalho isolado usam atributos para definir a função. Em vez disso, o script C# usa um arquivo de configuração function.json.

A tabela a seguir explica as propriedades do atributo SignalRConnectionInfoInput:

Propriedade de atributo Descrição
HubName Obrigatória. O nome do hub.
ConnectionStringSetting O nome da configuração do aplicativo que contém a cadeia de conexão do Serviço do SignalR (o padrão é AzureSignalRConnectionString).
UserId Opcional. O identificador de usuário de uma conexão do SignalR. É possível usar uma expressão de associação para associar o valor a um cabeçalho ou consulta de solicitação HTTP.
IdToken Opcional. Um token JWT cujas declarações serão adicionadas às declarações do usuário. Ele deve ser usado juntamente com ClaimTypeList. É possível usar uma expressão de associação para associar o valor a um cabeçalho ou consulta de solicitação HTTP.
ClaimTypeList Opcional. Uma lista de tipos de declaração que filtram as declarações no IdToken.

Anotações

A tabela a seguir explica as configurações com suporte para a anotação SignalRConnectionInfoInput.

Configuração Descrição
name Nome da variável usada no código de função para o objeto de informações de conexão.
hubName Obrigatória. O nome do hub.
connectionStringSetting O nome da configuração do aplicativo que contém a cadeia de conexão do Serviço do SignalR (o padrão é AzureSignalRConnectionString).
userId Opcional. O identificador de usuário de uma conexão do SignalR. É possível usar uma expressão de associação para associar o valor a um cabeçalho ou consulta de solicitação HTTP.
idToken Opcional. Um token JWT cujas declarações serão adicionadas às declarações do usuário. Ele deve ser usado juntamente com claimTypeList. É possível usar uma expressão de associação para associar o valor a um cabeçalho ou consulta de solicitação HTTP.
claimTypeList Opcional. Uma lista de tipos de declaração que filtram as declarações no idToken.

Anotações

A tabela a seguir explica as configurações com suporte para a anotação SignalRConnectionInfoInput.

Configuração Descrição
name Nome da variável usada no código de função para o objeto de informações de conexão.
hubName Obrigatória. O nome do hub.
connectionStringSetting O nome da configuração do aplicativo que contém a cadeia de conexão do Serviço do SignalR (o padrão é AzureSignalRConnectionString).
userId Opcional. O identificador de usuário de uma conexão do SignalR. É possível usar uma expressão de associação para associar o valor a um cabeçalho ou consulta de solicitação HTTP.
idToken Opcional. Um token JWT cujas declarações serão adicionadas às declarações do usuário. Ele deve ser usado juntamente com claimTypeList. É possível usar uma expressão de associação para associar o valor a um cabeçalho ou consulta de solicitação HTTP.
claimTypeList Opcional. Uma lista de tipos de declaração que filtram as declarações no idToken.

Configuração

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

Propriedade function.json Descrição
tipo Deve ser definido como signalRConnectionInfo.
direction Deve ser definido como in.
hubName Obrigatória. O nome do hub.
connectionStringSetting O nome da configuração do aplicativo que contém a cadeia de conexão do Serviço do SignalR (o padrão é AzureSignalRConnectionString).
userId Opcional. O identificador de usuário de uma conexão do SignalR. É possível usar uma expressão de associação para associar o valor a um cabeçalho ou consulta de solicitação HTTP.
idToken Opcional. Um token JWT cujas declarações serão adicionadas às declarações do usuário. Ele deve ser usado juntamente com claimTypeList. É possível usar uma expressão de associação para associar o valor a um cabeçalho ou consulta de solicitação HTTP.
claimTypeList Opcional. Uma lista de tipos de declaração que filtram as declarações no idToken.

Expressões de associação para gatilho HTTP

É um cenário comum em que os valores de alguns atributos da associação de entrada do SignalR são provenientes de solicitações HTTP. Portanto, mostramos como associar valores de solicitações HTTP a atributos de associação de entrada do SignalR por meio de expressão de associação.

Tipo de metadados HTTP Formato de expressão de associação Descrição Exemplo
Consulta de solicitação HTTP {query.QUERY_PARAMETER_NAME} Associa o valor do parâmetro de consulta correspondente a um atributo {query.userName}
Cabeçalho de solicitação HTTP {headers.HEADER_NAME} Associa o valor de um cabeçalho a um atributo {headers.token}

Próximas etapas