De eerste aanvraag tussen een client en een server is de onderhandelingsaanvraag. Wanneer u zelf-hostende SignalR gebruikt, gebruikt u de aanvraag om een verbinding tot stand te brengen tussen de client en de server. En wanneer u Azure SignalR Service gebruikt, maken clients verbinding met de service in plaats van de toepassingsserver. Dit artikel bevat concepten over onderhandelingsprotocollen en manieren om een onderhandelingseindpunt aan te passen.
Belangrijk
Onbewerkte verbindingsreeks worden alleen in dit artikel weergegeven voor demonstratiedoeleinden.
Een verbindingsreeks bevat de autorisatiegegevens die nodig zijn voor uw toepassing om toegang te krijgen tot Azure SignalR Service. De toegangssleutel in de verbindingsreeks is vergelijkbaar met een hoofdwachtwoord voor uw service. Beveilig uw toegangssleutels altijd in productieomgevingen. Gebruik Azure Key Vault om uw sleutels veilig te beheren en te roteren en uw verbindingsreeks te beveiligen met behulp van Microsoft Entra-id en toegang te autoriseren met Microsoft Entra ID.
Vermijd het distribueren van toegangssleutels naar andere gebruikers, het coderen ervan of het opslaan van ze ergens in tekst zonder opmaak die toegankelijk is voor anderen. Draai uw sleutels als u denkt dat ze mogelijk zijn aangetast.
Wat is onderhandelen?
Het antwoord op de aanvraag bevat een van de POST [endpoint-base]/negotiate volgende drie typen antwoorden:
Een antwoord dat connectionIdde verbinding op de server identificeert en de lijst met transporten die de server ondersteunt:
De nettolading die door dit eindpunt wordt geretourneerd, bevat de volgende gegevens:
De connectionId waarde is vereist door de LongPolling transporten ServerSentEvents om het verzenden en ontvangen te correleren.
De negotiateVersion waarde is de onderhandelingsprotocolversie die u gebruikt tussen de server en de client, zie Transportprotocollen.
negotiateVersion: 0 retourneert connectionIdalleen en de client moet de waarde van connectionId net als id in verbindingsaanvragen gebruiken.
negotiateVersion: 1 retourneert connectionId en connectionToken, en de client moet de waarde van connectionToken net als id in verbindingsaanvragen gebruiken.
In availableTransports de lijst worden de transporten beschreven die door de server worden ondersteund. Voor elk transport vermeldt de nettolading de naam van het transport (transport) en een lijst met overdrachtsindelingen die door het transport worden ondersteund (transferFormats).
Een omleidingsantwoord waarmee de client doorgeeft welke URL en (optioneel) toegangstoken moet worden gebruikt:
De nettolading die door dit eindpunt wordt geretourneerd, bevat de volgende gegevens:
De url waarde is de URL waarmee de client verbinding moet maken.
De accessToken waarde is een optioneel Bearer-token voor toegang tot de opgegeven URL.
Een antwoord dat een error vermelding bevat die de verbindingspoging moet stoppen:
JSON
{
"error": "This connection is not allowed."
}
De nettolading die door dit eindpunt wordt geretourneerd, bevat de volgende gegevens:
De error tekenreeks geeft details over waarom de onderhandeling is mislukt.
Wanneer u Azure SignalR Service gebruikt, maken clients verbinding met de service in plaats van de app-server. Er zijn drie stappen voor het tot stand brengen van permanente verbindingen tussen de client en Azure SignalR Service:
Een client verzendt een onderhandelingsaanvraag naar de app-server.
De app-server gebruikt de Azure SignalR Service SDK om een omleidingsantwoord te retourneren dat de URL en het toegangstoken van de Azure SignalR Service bevat.
Voor ASP.NET Core SignalR ziet een typisch omleidingsantwoord er als volgt uit:
Nadat de client het omleidingsantwoord heeft ontvangen, wordt de URL en het toegangstoken gebruikt om verbinding te maken met SignalR Service. De service stuurt de client vervolgens naar de app-server.
Belangrijk
In zelf-hostende SignalR kunnen sommige gebruikers ervoor kiezen om clientonderhandeling over te slaan wanneer clients alleen WebSocket ondersteunen en de retour voor onderhandeling opslaan. Wanneer u echter met Azure SignalR Service werkt, moeten clients altijd een vertrouwde server of een vertrouwd verificatiecentrum vragen om het toegangstoken te bouwen. Stel dit dus niet in SkipNegotiationtrue op de clientzijde.
SkipNegotiation betekent dat clients het toegangstoken zelf moeten bouwen. Deze instelling brengt een beveiligingsrisico met zich mee dat de client iets kan doen aan het service-eindpunt.
Wat kunt u doen tijdens de onderhandeling?
Aangepaste instellingen voor clientverbindingen
U kunt de clientverbinding instellen om instellingen voor beveiliging of bedrijfsbehoeften aan te passen. Voorbeeld:
Gebruik een korte AccessTokenLifetime waarde voor beveiliging.
Geef alleen de benodigde gegevens van clientclaims door.
Voeg aangepaste claims toe voor zakelijke behoeften.
cs
services.AddSignalR().AddAzureSignalR(options =>
{
// Pass only necessary information in the negotiation step
options.ClaimsProvider = context => new[]
{
new Claim(ClaimTypes.NameIdentifier, context.Request.Query["username"]),
new Claim("<Custom Claim Name>", "<Custom Claim Value>")
};
options.AccessTokenLifetime = TimeSpan.FromMinutes(5);
});
Server stickiness
Wanneer u meerdere app-servers hebt, is er geen garantie (standaard) dat de server die onderhandelen uitvoert en de server die de hub aanroep krijgt, hetzelfde is. In sommige gevallen wilt u mogelijk clientstatusgegevens lokaal laten onderhouden op de app-server.
Wanneer u bijvoorbeeld Blazor aan de serverzijde gebruikt, blijft de gebruikersinterfacestatus behouden aan de serverzijde. U wilt dus dat alle clientaanvragen naar dezelfde server gaan, inclusief de SignalR-verbinding. Vervolgens moet u de server sticky-modus Required inschakelen tijdens de onderhandeling:
Een andere manier waarop u onderhandeling kunt aanpassen, is in meerdere eindpunten. Omdat de app-server de service-URL levert als het onderhandelingsantwoord, kan de app-server bepalen welk eindpunt moet worden geretourneerd naar clients voor taakverdeling en communicatie-efficiëntie. Dat wil gezegd, u kunt de client verbinding laten maken met het dichtstbijzijnde service-eindpunt om verkeerskosten te besparen.
cs
// Sample of a custom routerprivateclassCustomRouter : EndpointRouterDecorator
{
publicoverride ServiceEndpoint GetNegotiateEndpoint(HttpContext context, IEnumerable<ServiceEndpoint> endpoints)
{
// Override the negotiation behavior to get the endpoint from the query stringvar endpointName = context.Request.Query["endpoint"];
if (endpointName.Count == 0)
{
context.Response.StatusCode = 400;
var response = Encoding.UTF8.GetBytes("Invalid request");
context.Response.Body.Write(response, 0, response.Length);
returnnull;
}
return endpoints.FirstOrDefault(s => s.Name == endpointName && s.Online) // Get the endpoint with the name that matches the incoming request
?? base.GetNegotiateEndpoint(context, endpoints); // Fall back to the default behavior to randomly select one from primary endpoints, or fall back to secondary when no primary ones are online
}
}
Registreer ook de router voor afhankelijkheidsinjectie.
// Sample of configuring multiple endpoints and dependency injection
services.AddSingleton(typeof(IEndpointRouter), typeof(CustomRouter));
services.AddSignalR().AddAzureSignalR(
options =>
{
options.Endpoints = new ServiceEndpoint[]
{
new ServiceEndpoint(name: "east", connectionString: "<connectionString1>"),
new ServiceEndpoint(name: "west", connectionString: "<connectionString2>"),
new ServiceEndpoint("<connectionString3>")
};
});
Hoe kunt u een eindpunt voor clientonderhandeling toevoegen in de serverloze modus?
In de serverloze modus (Serverless) accepteert geen server SignalR-clients. Om uw verbindingsreeks te beschermen, moet u SignalR-clients omleiden van het onderhandelingseindpunt naar Azure SignalR Service in plaats van uw verbindingsreeks aan alle SignalR-clients te geven.
De aanbevolen procedure is om een onderhandelingseindpunt te hosten. Vervolgens kunt u SignalR-clients gebruiken voor dit eindpunt en de service-URL en het toegangstoken ophalen.
Azure SignalR Service Management SDK
U kunt onderhandelen benaderen door te werken met de Management SDK.
U kunt het exemplaar gebruiken van het genereren van ServiceHubContext de eindpunt-URL en het bijbehorende toegangstoken voor SignalR-clients om verbinding te maken met Azure SignalR Service:
cs
var negotiationResponse = await serviceHubContext.NegotiateAsync(new (){ UserId = "<Your User Id>" });
Stel dat uw hub-eindpunt is http://<Your Host Name>/<Your Hub Name>. Vervolgens is http://<Your Host Name>/<Your Hub Name>/negotiateuw onderhandelingseindpunt. Nadat u het onderhandelingseindpunt hebt gehost, kunt u de SignalR-clients gebruiken om verbinding te maken met uw hub:
cs
var connection = new HubConnectionBuilder().WithUrl("http://<Your Host Name>/<Your Hub Name>").Build();
await connection.StartAsync();
U vindt een volledig voorbeeld over het gebruik van de Management SDK om SignalR-clients om te leiden naar Azure SignalR Service op GitHub.
Functie-extensie van Azure SignalR Service
Wanneer u een Azure-functie-app gebruikt, kunt u met de functie-extensie werken. Hier volgt een voorbeeld van het gebruik SignalRConnectionInfo van een geïsoleerd C#-werkrolmodel om u te helpen bij het opbouwen van het onderhandelingsantwoord:
C#
[Function(nameof(Negotiate))]
publicstaticstringNegotiate([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;
}
Waarschuwing
Ter vereenvoudiging laten we de verificatie- en autorisatieonderdelen in dit voorbeeld weg. Hierdoor is dit eindpunt openbaar toegankelijk zonder beperkingen. Om de beveiliging van uw onderhandelingseindpunt te waarborgen, moet u de juiste verificatie- en autorisatiemechanismen implementeren op basis van uw specifieke vereisten. Zie de volgende artikelen voor hulp bij het beveiligen van uw HTTP-eindpunten:
Vervolgens kunnen uw clients het functie-eindpunt https://<Your Function App Name>.azurewebsites.net/api/negotiate aanvragen om de service-URL en het toegangstoken op te halen. U vindt een volledig voorbeeld op GitHub.
U kunt het onderhandelingseindpunt ook beschikbaar maken op uw eigen server en het onderhandelingsantwoord zelf retourneren als u andere talen gebruikt.
ConnectionString gebruiken
Hieronder ziet u een pseudocode in JavaScript waarin wordt getoond hoe u het onderhandelingseindpunt voor hubs chat implementeert en een toegangstoken genereert vanuit Azure SignalR verbindingsreeks.
Een JavaScript SignalR-client maakt vervolgens verbinding met de URL /chat:
JavaScript
let connection = new signalR.HubConnectionBuilder().withUrl('/chat').build();
connection.start();
Microsoft Entra-id gebruiken
Azure SignalR biedt ook REST API POST /api/hubs/${hub}/:generateToken?api-version=2022-11-01&userId=${userId}&minutesToExpire=${minutesToExpire} om het clienttoegangstoken voor u te genereren wanneer u Microsoft Entra-id gebruikt.
Dit zijn de stappen:
Volg roltoewijzingen toevoegen om een rol SignalR REST API Owner toe te wijzen of SignalR Service Owner aan uw identiteit, zodat uw identiteit gemachtigd is om de REST API aan te roepen om het toegangstoken voor de client te genereren.
Azure Identity-clientbibliotheek gebruiken om het Microsoft Entra ID-token met bereik op te halen https://signalr.azure.com/.default
Gebruik dit token om de REST API voor het genereren van tokens te bezoeken
Retourneert het clienttoegangstoken in het onderhandelingsantwoord.
Hieronder ziet u een pseudocode in JavaScript waarin wordt getoond hoe u het onderhandelingseindpunt voor de hub chat implementeert en toegangstoken opvragen met behulp van Microsoft Entra ID en REST API /generateToken.
JavaScript
import express from"express";
import axios from"axios";
import { DefaultAzureCredential } from"@azure/identity";
const endpoint = "https://<your-service>.service.signalr.net";
const hub = "chat";
const generateTokenUrl = `${endpoint}/api/hubs/${hub}/:generateToken?api-version=2022-11-01`;
let app = express();
app.get("/chat/negotiate", async (req, res) => {
// use DefaultAzureCredential to get the Entra ID token to call the Azure SignalR REST APIconst credential = new DefaultAzureCredential();
const entraIdToken = await credential.getToken("https://signalr.azure.com/.default");
const token = (
await axios.post(generateTokenUrl, undefined, {
headers: {
"content-type": "application/json",
Authorization: `Bearer ${entraIdToken.token}`,
},
})
).data.token;
let url = `${endpoint}/client/?hub=${hub}`;
res.json({ url: url, accessToken: token });
});
app.listen(8080, () => console.log("server started"));
Volgende stappen
Zie de volgende artikelen voor meer informatie over het gebruik van standaard- en serverloze modi:
Wijzig een updatemechanisme voor JavaScript-web-apps van polling naar realtime push-gebaseerde architectuur met SignalR Service, Azure Cosmos DB en Azure Functions. Gebruik Vue.js en JavaScript om SignalR te gebruiken met Visual Studio Code.
In dit artikel vindt u een overzicht van verbindingsreeks s in Azure SignalR Service, hoe u er een genereert en hoe u er een configureert in een app-server.