Considérations relatives à la sécurité avec ASP.NET Core SignalR

Par Andrew Stanton-Nurse

Cet article fournit des informations sur la sécurisation de SignalR.

Partage des ressources cross-origin

Le partage des ressources Cross-Origin (CORS) peut être utilisé pour autoriser les connexions Cross-Origin SignalR dans le navigateur. Si le code JavaScript est hébergé sur un domaine différent de l’applicationSignalR, l’intergiciel CORS doit être activé pour permettre à JavaScript de se connecter à l’applicationSignalR. Autorisez les demandes cross-origin uniquement à partir de domaines que vous approuvez ou contrôlez. Par exemple :

  • Votre site est hébergé sur http://www.example.com
  • Votre SignalR application est hébergée sur http://signalr.example.com

CORS doit être configuré dans l’application SignalR pour autoriser uniquement l’origine www.example.com.

Pour plus d’informations sur la configuration de CORS, consultez Activer les demandes cross-origin (CORS). SignalRnécessite les stratégies CORS suivantes :

  • Autorisez les origines attendues spécifiques. L’autorisation de n’importe quelle origine est possible, mais n’est pas sécurisée ou recommandée.
  • Les méthodes GET HTTP et POST doivent être autorisées.
  • Les informations d’identification doivent être autorisées pour que les sessions persistantes basées sur cookie fonctionnent correctement. Elles doivent être activées même lorsque l’authentification n’est pas utilisée.

Toutefois, dans la version 5.0, nous avons fourni une option dans le client TypeScript pour ne pas utiliser les informations d’identification. L’option de ne pas utiliser d’informations d’identification ne doit être utilisée que lorsque vous savez à 100 % que les informations d’identification comme Cookies ne sont pas nécessaires dans votre application (cookieelles sont utilisées par Azure App Service lors de l’utilisation de plusieurs serveurs pour les sessions persistantes).

Par exemple, la stratégie CORS suivante mise en évidence permet à un client de navigateur SignalR hébergé sur https://example.com d’accéder à l’application SignalR hébergée sur https://signalr.example.com :

using SignalRChat.Hubs;

var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy(name: MyAllowSpecificOrigins,
                      policy =>
                      {
                          policy.WithOrigins("http://example.com");
                          policy.WithMethods("GET", "POST");
                          policy.AllowCredentials();
                      });
});

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddSignalR();

var app = builder.Build();

app.MapHub<ChatHub>("/chatHub");

Dans l’exemple précédent, la stratégie CORS était personnalisée pour autoriser des origines, des méthodes et des informations d’identification spécifiques. Pour plus d’informations sur la personnalisation des stratégies CORS et d’un intergiciel dans ASP.NET Core, consultez Intergiciel CORS : CORS avec une stratégie nommée et un intergiciel.

Restriction d’origine WebSocket

Les protections fournies par CORS ne s’appliquent pas aux WebSockets. Pour la restriction d’origine sur les WebSockets, lisez Restriction d’origine WebSockets.

ConnectionId

L’exposition ConnectionId peut entraîner un emprunt d’identité malveillant si la version SignalR du serveur ou du client est ASP.NET Core version 2.2 ou antérieure. Si la version SignalR du serveur et du client est ASP.NET Core 3.0 ou ultérieure, le ConnectionToken plutôt que le ConnectionId doit rester secret. Le ConnectionToken n’est volontairement exposé dans aucune API. Il peut être difficile de s’assurer que les clients plus anciens SignalR ne se connectent pas au serveur. Par conséquent, même si la version de votre SignalR serveur est ASP.NET Core 3.0 ou ultérieure, le ConnectionId ne doit pas être exposé.

Journalisation des jetons d’accès

Lors de l’utilisation de WebSockets ou d’événements Server-Sent, le client du navigateur envoie le jeton d’accès dans la chaîne de requête. La réception du jeton d’accès via une chaîne de requête est généralement aussi sécurisée que l’utilisation de l’en-tête standard Authorization. Utilisez toujours HTTPS pour garantir une connexion de bout en bout sécurisée entre le client et le serveur. De nombreux serveurs web journalisent l’URL de chaque requête, y compris la chaîne de requête. La journalisation des URL peut enregistrer le jeton d’accès. ASP.NET Core journalise l’URL de chaque requête par défaut, qui inclut la chaîne de requête. Par exemple :

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:5000/chathub?access_token=1234

Si vous avez des préoccupations concernant la Microsoft.AspNetCore.Hosting journalisation de ces données avec vos journaux de serveur, vous pouvez désactiver cette journalisation entièrement en configurant l’enregistreur Warning d’événements au niveau ou au-dessus (ces messages sont écrits au Info niveau). Pour plus d’informations, consultez Appliquer des règles de filtre de journal dans le code pour plus d’informations. Si vous souhaitez toujours journaliser certaines informations de demande, vous pouvez écrire un intergiciel pour journaliser les données dont vous avez besoin et filtrer la valeur de chaîne de requête (le access_token cas échéant).

Exceptions

Les messages d’exception sont généralement considérés comme des données sensibles qui ne doivent pas être révélées à un client. Par défaut, SignalR n’envoie pas les détails d’une exception levée par une méthode hub au client. Au lieu de cela, le client reçoit un message générique indiquant qu’une erreur s’est produite. La remise de messages d’exception au client peut être remplacée (par exemple en développement ou en test) avec EnableDetailedErrors. Les messages d’exception ne doivent pas être exposés au client dans les applications de production.

Gestion des tampons

SignalR utilise des mémoires tampons par connexion pour gérer les messages entrants et sortants. Par défaut, SignalR limite ces mémoires tampons à 32 Ko. Le plus grand message qu’un client ou un serveur peut envoyer est de 32 Ko. La mémoire maximale consommée par une connexion pour les messages est de 32 Ko. Si vos messages sont toujours inférieurs à 32 Ko, vous pouvez réduire la limite, ce qui :

  • Empêche un client de pouvoir envoyer un message plus volumineux.
  • Le serveur n’aura jamais besoin d’allouer de mémoires tampons volumineuses pour accepter les messages.

Si la taille de vos messages est supérieure à 32 Ko, vous pouvez augmenter la limite. L’augmentation de cette limite signifie :

  • Le client peut amener le serveur à allouer des mémoires tampons volumineuses.
  • L’allocation par serveur de mémoires tampons volumineuses peut réduire le nombre de connexions simultanées.

Il existe des limites pour les messages entrants et sortants. Les deux peuvent être configurés sur l’objet HttpConnectionDispatcherOptions configuré dans MapHub :

  • ApplicationMaxBufferSize représente le nombre maximal d’octets du client que le serveur met en mémoire tampon. Si le client tente d’envoyer un message supérieur à cette limite, la connexion peut être fermée.
  • TransportMaxBufferSize représente le nombre maximal d’octets que le serveur peut envoyer. Si le serveur tente d’envoyer un message (y compris les valeurs de retour des méthodes hub) supérieur à cette limite, une exception est levée.

La définition de la limite sur 0 désactive la limite. La suppression de la limite permet à un client d’envoyer un message de toute taille. Les clients malveillants qui envoient des messages volumineux peuvent entraîner l’allocation de mémoire excédentaire. L’utilisation excessive de la mémoire peut réduire considérablement le nombre de connexions simultanées.

Cet article fournit des informations sur la sécurisation de SignalR.

Partage des ressources cross-origin

Le partage des ressources Cross-Origin (CORS) peut être utilisé pour autoriser les connexions Cross-Origin SignalR dans le navigateur. Si le code JavaScript est hébergé sur un domaine différent de l’applicationSignalR, l’intergiciel CORS doit être activé pour permettre à JavaScript de se connecter à l’applicationSignalR. Autorisez les demandes cross-origin uniquement à partir de domaines que vous approuvez ou contrôlez. Par exemple :

  • Votre site est hébergé sur http://www.example.com
  • Votre SignalR application est hébergée sur http://signalr.example.com

CORS doit être configuré dans l’application SignalR pour autoriser uniquement l’origine www.example.com.

Pour plus d’informations sur la configuration de CORS, consultez Activer les demandes cross-origin (CORS). SignalRnécessite les stratégies CORS suivantes :

  • Autorisez les origines attendues spécifiques. L’autorisation de n’importe quelle origine est possible, mais n’est pas sécurisée ou recommandée.
  • Les méthodes GET HTTP et POST doivent être autorisées.
  • Les informations d’identification doivent être autorisées pour que les sessions persistantes basées sur cookie fonctionnent correctement. Elles doivent être activées même lorsque l’authentification n’est pas utilisée.

Toutefois, dans la version 5.0, nous avons fourni une option dans le client TypeScript pour ne pas utiliser les informations d’identification. L’option de ne pas utiliser d’informations d’identification ne doit être utilisée que lorsque vous savez à 100 % que les informations d’identification comme Cookies ne sont pas nécessaires dans votre application (cookieelles sont utilisées par Azure App Service lors de l’utilisation de plusieurs serveurs pour les sessions persistantes).

Par exemple, la stratégie CORS suivante mise en évidence permet à un client de navigateur SignalR hébergé sur https://example.com d’accéder à l’application SignalR hébergée sur https://signalr.example.com :

using SignalRChat.Hubs;

var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy(name: MyAllowSpecificOrigins,
                      policy =>
                      {
                          policy.WithOrigins("http://example.com");
                          policy.WithMethods("GET", "POST");
                          policy.AllowCredentials();
                      });
});

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddSignalR();

var app = builder.Build();

app.MapHub<ChatHub>("/chatHub");

Dans l’exemple précédent, la stratégie CORS était personnalisée pour autoriser des origines, des méthodes et des informations d’identification spécifiques. Pour plus d’informations sur la personnalisation des stratégies CORS et d’un intergiciel dans ASP.NET Core, consultez Intergiciel CORS : CORS avec une stratégie nommée et un intergiciel.

Restriction d’origine WebSocket

Les protections fournies par CORS ne s’appliquent pas aux WebSockets. Pour la restriction d’origine sur les WebSockets, lisez Restriction d’origine WebSockets.

ConnectionId

L’exposition ConnectionId peut entraîner un emprunt d’identité malveillant si la version SignalR du serveur ou du client est ASP.NET Core version 2.2 ou antérieure. Si la version SignalR du serveur et du client est ASP.NET Core 3.0 ou ultérieure, le ConnectionToken plutôt que le ConnectionId doit rester secret. Le ConnectionToken n’est volontairement exposé dans aucune API. Il peut être difficile de s’assurer que les clients plus anciens SignalR ne se connectent pas au serveur. Par conséquent, même si la version de votre SignalR serveur est ASP.NET Core 3.0 ou ultérieure, le ConnectionId ne doit pas être exposé.

Journalisation des jetons d’accès

Lors de l’utilisation de WebSockets ou d’événements Server-Sent, le client du navigateur envoie le jeton d’accès dans la chaîne de requête. La réception du jeton d’accès via une chaîne de requête est généralement aussi sécurisée que l’utilisation de l’en-tête standard Authorization. Utilisez toujours HTTPS pour garantir une connexion de bout en bout sécurisée entre le client et le serveur. De nombreux serveurs web journalisent l’URL de chaque requête, y compris la chaîne de requête. La journalisation des URL peut enregistrer le jeton d’accès. ASP.NET Core journalise l’URL de chaque requête par défaut, qui inclut la chaîne de requête. Par exemple :

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:5000/chathub?access_token=1234

Si vous avez des préoccupations concernant la Microsoft.AspNetCore.Hosting journalisation de ces données avec vos journaux de serveur, vous pouvez désactiver cette journalisation entièrement en configurant l’enregistreur Warning d’événements au niveau ou au-dessus (ces messages sont écrits au Info niveau). Pour plus d’informations, consultez Appliquer des règles de filtre de journal dans le code pour plus d’informations. Si vous souhaitez toujours journaliser certaines informations de demande, vous pouvez écrire un intergiciel pour journaliser les données dont vous avez besoin et filtrer la valeur de chaîne de requête (le access_token cas échéant).

Exceptions

Les messages d’exception sont généralement considérés comme des données sensibles qui ne doivent pas être révélées à un client. Par défaut, SignalR n’envoie pas les détails d’une exception levée par une méthode hub au client. Au lieu de cela, le client reçoit un message générique indiquant qu’une erreur s’est produite. La remise de messages d’exception au client peut être remplacée (par exemple en développement ou en test) avec EnableDetailedErrors. Les messages d’exception ne doivent pas être exposés au client dans les applications de production.

Gestion des tampons

SignalR utilise des mémoires tampons par connexion pour gérer les messages entrants et sortants. Par défaut, SignalR limite ces mémoires tampons à 32 Ko. Le plus grand message qu’un client ou un serveur peut envoyer est de 32 Ko. La mémoire maximale consommée par une connexion pour les messages est de 32 Ko. Si vos messages sont toujours inférieurs à 32 Ko, vous pouvez réduire la limite, ce qui :

  • Empêche un client de pouvoir envoyer un message plus volumineux.
  • Le serveur n’aura jamais besoin d’allouer de mémoires tampons volumineuses pour accepter les messages.

Si la taille de vos messages est supérieure à 32 Ko, vous pouvez augmenter la limite. L’augmentation de cette limite signifie :

  • Le client peut amener le serveur à allouer des mémoires tampons volumineuses.
  • L’allocation par serveur de mémoires tampons volumineuses peut réduire le nombre de connexions simultanées.

Il existe des limites pour les messages entrants et sortants. Les deux peuvent être configurés sur l’objet HttpConnectionDispatcherOptions configuré dans MapHub :

  • ApplicationMaxBufferSize représente le nombre maximal d’octets du client que le serveur met en mémoire tampon. Si le client tente d’envoyer un message supérieur à cette limite, la connexion peut être fermée.
  • TransportMaxBufferSize représente le nombre maximal d’octets que le serveur peut envoyer. Si le serveur tente d’envoyer un message (y compris les valeurs de retour des méthodes hub) supérieur à cette limite, une exception est levée.

La définition de la limite sur 0 désactive la limite. La suppression de la limite permet à un client d’envoyer un message de toute taille. Les clients malveillants qui envoient des messages volumineux peuvent entraîner l’allocation de mémoire excédentaire. L’utilisation excessive de la mémoire peut réduire considérablement le nombre de connexions simultanées.

Cet article fournit des informations sur la sécurisation de SignalR.

Partage des ressources cross-origin

Le partage des ressources Cross-Origin (CORS) peut être utilisé pour autoriser les connexions Cross-Origin SignalR dans le navigateur. Si le code JavaScript est hébergé sur un domaine différent de l’applicationSignalR, l’intergiciel CORS doit être activé pour permettre à JavaScript de se connecter à l’applicationSignalR. Autorisez les demandes cross-origin uniquement à partir de domaines que vous approuvez ou contrôlez. Par exemple :

  • Votre site est hébergé sur http://www.example.com
  • Votre SignalR application est hébergée sur http://signalr.example.com

CORS doit être configuré dans l’application SignalR pour autoriser uniquement l’origine www.example.com.

Pour plus d’informations sur la configuration de CORS, consultez Activer les demandes cross-origin (CORS). SignalRnécessite les stratégies CORS suivantes :

  • Autorisez les origines attendues spécifiques. L’autorisation de n’importe quelle origine est possible, mais n’est pas sécurisée ou recommandée.
  • Les méthodes GET HTTP et POST doivent être autorisées.
  • Les informations d’identification doivent être autorisées pour que les sessions persistantes basées sur cookie fonctionnent correctement. Elles doivent être activées même lorsque l’authentification n’est pas utilisée.

Toutefois, dans la version 5.0, nous avons fourni une option dans le client TypeScript pour ne pas utiliser les informations d’identification. L’option de ne pas utiliser d’informations d’identification ne doit être utilisée que lorsque vous savez à 100 % que les informations d’identification comme Cookies ne sont pas nécessaires dans votre application (cookieelles sont utilisées par Azure App Service lors de l’utilisation de plusieurs serveurs pour les sessions persistantes).

Par exemple, la stratégie CORS suivante mise en évidence permet à un client de navigateur SignalR hébergé sur https://example.com d’accéder à l’application SignalR hébergée sur https://signalr.example.com :

using SignalRChat.Hubs;

var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy(name: MyAllowSpecificOrigins,
                      policy =>
                      {
                          policy.WithOrigins("http://example.com");
                          policy.WithMethods("GET", "POST");
                          policy.AllowCredentials();
                      });
});

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddSignalR();

var app = builder.Build();

app.MapHub<ChatHub>("/chatHub");

Dans l’exemple précédent, la stratégie CORS était personnalisée pour autoriser des origines, des méthodes et des informations d’identification spécifiques. Pour plus d’informations sur la personnalisation des stratégies CORS et d’un intergiciel dans ASP.NET Core, consultez Intergiciel CORS : CORS avec une stratégie nommée et un intergiciel.

Restriction d’origine WebSocket

Les protections fournies par CORS ne s’appliquent pas aux WebSockets. Pour la restriction d’origine sur les WebSockets, lisez Restriction d’origine WebSockets.

ConnectionId

L’exposition ConnectionId peut entraîner un emprunt d’identité malveillant si la version SignalR du serveur ou du client est ASP.NET Core version 2.2 ou antérieure. Si la version SignalR du serveur et du client est ASP.NET Core 3.0 ou ultérieure, le ConnectionToken plutôt que le ConnectionId doit rester secret. Le ConnectionToken n’est volontairement exposé dans aucune API. Il peut être difficile de s’assurer que les clients plus anciens SignalR ne se connectent pas au serveur. Par conséquent, même si la version de votre SignalR serveur est ASP.NET Core 3.0 ou ultérieure, le ConnectionId ne doit pas être exposé.

Journalisation des jetons d’accès

Lors de l’utilisation de WebSockets ou d’événements Server-Sent, le client du navigateur envoie le jeton d’accès dans la chaîne de requête. La réception du jeton d’accès via une chaîne de requête est généralement aussi sécurisée que l’utilisation de l’en-tête standard Authorization. Utilisez toujours HTTPS pour garantir une connexion de bout en bout sécurisée entre le client et le serveur. De nombreux serveurs web journalisent l’URL de chaque requête, y compris la chaîne de requête. La journalisation des URL peut enregistrer le jeton d’accès. ASP.NET Core journalise l’URL de chaque requête par défaut, qui inclut la chaîne de requête. Par exemple :

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:5000/chathub?access_token=1234

Si vous avez des préoccupations concernant la Microsoft.AspNetCore.Hosting journalisation de ces données avec vos journaux de serveur, vous pouvez désactiver cette journalisation entièrement en configurant l’enregistreur Warning d’événements au niveau ou au-dessus (ces messages sont écrits au Info niveau). Pour plus d’informations, consultez Appliquer des règles de filtre de journal dans le code pour plus d’informations. Si vous souhaitez toujours journaliser certaines informations de demande, vous pouvez écrire un intergiciel pour journaliser les données dont vous avez besoin et filtrer la valeur de chaîne de requête (le access_token cas échéant).

Exceptions

Les messages d’exception sont généralement considérés comme des données sensibles qui ne doivent pas être révélées à un client. Par défaut, SignalR n’envoie pas les détails d’une exception levée par une méthode hub au client. Au lieu de cela, le client reçoit un message générique indiquant qu’une erreur s’est produite. La remise de messages d’exception au client peut être remplacée (par exemple en développement ou en test) avec EnableDetailedErrors. Les messages d’exception ne doivent pas être exposés au client dans les applications de production.

Gestion des tampons

SignalR utilise des mémoires tampons par connexion pour gérer les messages entrants et sortants. Par défaut, SignalR limite ces mémoires tampons à 32 Ko. Le plus grand message qu’un client ou un serveur peut envoyer est de 32 Ko. La mémoire maximale consommée par une connexion pour les messages est de 32 Ko. Si vos messages sont toujours inférieurs à 32 Ko, vous pouvez réduire la limite, ce qui :

  • Empêche un client de pouvoir envoyer un message plus volumineux.
  • Le serveur n’aura jamais besoin d’allouer de mémoires tampons volumineuses pour accepter les messages.

Si la taille de vos messages est supérieure à 32 Ko, vous pouvez augmenter la limite. L’augmentation de cette limite signifie :

  • Le client peut amener le serveur à allouer des mémoires tampons volumineuses.
  • L’allocation par serveur de mémoires tampons volumineuses peut réduire le nombre de connexions simultanées.

Il existe des limites pour les messages entrants et sortants. Les deux peuvent être configurés sur l’objet HttpConnectionDispatcherOptions configuré dans MapHub :

  • ApplicationMaxBufferSize représente le nombre maximal d’octets du client que le serveur met en mémoire tampon. Si le client tente d’envoyer un message supérieur à cette limite, la connexion peut être fermée.
  • TransportMaxBufferSize représente le nombre maximal d’octets que le serveur peut envoyer. Si le serveur tente d’envoyer un message (y compris les valeurs de retour des méthodes hub) supérieur à cette limite, une exception est levée.

La définition de la limite sur 0 désactive la limite. La suppression de la limite permet à un client d’envoyer un message de toute taille. Les clients malveillants qui envoient des messages volumineux peuvent entraîner l’allocation de mémoire excédentaire. L’utilisation excessive de la mémoire peut réduire considérablement le nombre de connexions simultanées.

Cet article fournit des informations sur la sécurisation de SignalR.

Partage des ressources cross-origin

Le partage des ressources Cross-Origin (CORS) peut être utilisé pour autoriser les connexions Cross-Origin SignalR dans le navigateur. Si le code JavaScript est hébergé sur un domaine différent de l’applicationSignalR, l’intergiciel CORS doit être activé pour permettre à JavaScript de se connecter à l’applicationSignalR. Autorisez les demandes cross-origin uniquement à partir de domaines que vous approuvez ou contrôlez. Par exemple :

  • Votre site est hébergé sur http://www.example.com
  • Votre SignalR application est hébergée sur http://signalr.example.com

CORS doit être configuré dans l’application SignalR pour autoriser uniquement l’origine www.example.com.

Pour plus d’informations sur la configuration de CORS, consultez Activer les demandes cross-origin (CORS). SignalRnécessite les stratégies CORS suivantes :

  • Autorisez les origines attendues spécifiques. L’autorisation de n’importe quelle origine est possible, mais n’est pas sécurisée ou recommandée.
  • Les méthodes GET HTTP et POST doivent être autorisées.
  • Les informations d’identification doivent être autorisées pour que les sessions persistantes basées sur cookie fonctionnent correctement. Elles doivent être activées même lorsque l’authentification n’est pas utilisée.

Toutefois, dans la version 5.0, nous avons fourni une option dans le client TypeScript pour ne pas utiliser les informations d’identification. L’option de ne pas utiliser d’informations d’identification ne doit être utilisée que lorsque vous savez à 100 % que les informations d’identification comme Cookies ne sont pas nécessaires dans votre application (cookieelles sont utilisées par Azure App Service lors de l’utilisation de plusieurs serveurs pour les sessions persistantes).

Par exemple, la stratégie CORS suivante permet à un SignalR client de navigateur hébergé sur https://example.com d’accéder à l’application SignalR hébergée sur https://signalr.example.com :

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // ... other middleware ...

    // Make sure the CORS middleware is ahead of SignalR.
    app.UseCors(builder =>
    {
        builder.WithOrigins("https://example.com")
            .AllowAnyHeader()
            .WithMethods("GET", "POST")
            .AllowCredentials();
    });

    // ... other middleware ...
    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapHub<ChatHub>("/chathub");
    });

    // ... other middleware ...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // ... other middleware ...

    // Make sure the CORS middleware is ahead of SignalR.
    app.UseCors(builder =>
    {
        builder.WithOrigins("https://example.com")
            .AllowAnyHeader()
            .WithMethods("GET", "POST")
            .AllowCredentials();
    });

    // ... other middleware ...

    app.UseSignalR(routes =>
    {
        routes.MapHub<ChatHub>("/chathub");
    });

    // ... other middleware ...
}

Restriction d’origine WebSocket

Les protections fournies par CORS ne s’appliquent pas aux WebSockets. Pour la restriction d’origine sur les WebSockets, lisez Restriction d’origine WebSockets.

Les protections fournies par CORS ne s’appliquent pas aux WebSockets. Les navigateurs :

  • n’effectuent pas de requêtes préalables CORS ;
  • respectent les restrictions spécifiées dans les en-têtes Access-Control quand ils effectuent des requêtes WebSocket.

Toutefois, les navigateurs envoient l’en-tête Origin au moment de l’émission des requêtes WebSocket. Les applications doivent être configurées de manière à valider ces en-têtes, le but étant de vérifier que seuls les WebSockets provenant des origines attendues sont autorisés.

Dans ASP.NET Core 2.1 et versions ultérieures, la validation d’en-tête peut être obtenue à l’aide d’un intergiciel personnalisé placé avant UseSignalRet d’un intergiciel d’authentification dans Configure :


// In Startup, add a static field listing the allowed Origin values:
private static readonly HashSet<string> _allowedOrigins = new HashSet<string>()
{
    // Add allowed origins here. For example:
    "https://www.mysite.com",
    "https://mysite.com",
};

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // ... other middleware ...

    // Validate Origin header on WebSocket requests to prevent unexpected cross-site 
    // WebSocket requests.
    app.Use((context, next) =>
    {
        // Check for a WebSocket request.
        if (string.Equals(context.Request.Headers["Upgrade"], "websocket"))
        {
            var origin = context.Request.Headers["Origin"];

            // If there is an origin header, and the origin header doesn't match 
            // an allowed value:
            if (!string.IsNullOrEmpty(origin) && !_allowedOrigins.Contains(origin))
            {
                // The origin is not allowed, reject the request
                context.Response.StatusCode = (int) HttpStatusCode.Forbidden;
                return Task.CompletedTask;
            }
        }

        // The request is a valid Origin or not a WebSocket request, so continue.
        return next();
    });

    // ... other middleware ...

    app.UseSignalR(routes =>
    {
        routes.MapHub<ChatHub>("/chathub");
    });

    // ... other middleware ...
}

Note

L’en-tête Origin est contrôlé par le client et, comme l’en-tête Referer, peut être falsifié. Ces en-têtes ne doivent pas être utilisés comme mécanisme d’authentification.

ConnectionId

L’exposition ConnectionId peut entraîner un emprunt d’identité malveillant si la version SignalR du serveur ou du client est ASP.NET Core version 2.2 ou antérieure. Si la version SignalR du serveur et du client est ASP.NET Core 3.0 ou ultérieure, le ConnectionToken plutôt que le ConnectionId doit rester secret. Le ConnectionToken n’est volontairement exposé dans aucune API. Il peut être difficile de s’assurer que les clients plus anciens SignalR ne se connectent pas au serveur. Par conséquent, même si la version de votre SignalR serveur est ASP.NET Core 3.0 ou ultérieure, le ConnectionId ne doit pas être exposé.

Journalisation des jetons d’accès

Lors de l’utilisation de WebSockets ou d’événements Server-Sent, le client du navigateur envoie le jeton d’accès dans la chaîne de requête. La réception du jeton d’accès via une chaîne de requête est généralement aussi sécurisée que l’utilisation de l’en-tête standard Authorization. Utilisez toujours HTTPS pour garantir une connexion de bout en bout sécurisée entre le client et le serveur. De nombreux serveurs web journalisent l’URL de chaque requête, y compris la chaîne de requête. La journalisation des URL peut enregistrer le jeton d’accès. ASP.NET Core journalise l’URL de chaque requête par défaut, qui inclut la chaîne de requête. Par exemple :

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:5000/chathub?access_token=1234

Si vous avez des préoccupations concernant la Microsoft.AspNetCore.Hosting journalisation de ces données avec vos journaux de serveur, vous pouvez désactiver cette journalisation entièrement en configurant l’enregistreur Warning d’événements au niveau ou au-dessus (ces messages sont écrits au Info niveau). Pour plus d’informations, consultez Appliquer des règles de filtre de journal dans le code pour plus d’informations. Si vous souhaitez toujours journaliser certaines informations de demande, vous pouvez écrire un intergiciel pour journaliser les données dont vous avez besoin et filtrer la valeur de chaîne de requête (le access_token cas échéant).

Exceptions

Les messages d’exception sont généralement considérés comme des données sensibles qui ne doivent pas être révélées à un client. Par défaut, SignalR n’envoie pas les détails d’une exception levée par une méthode hub au client. Au lieu de cela, le client reçoit un message générique indiquant qu’une erreur s’est produite. La remise de messages d’exception au client peut être remplacée (par exemple en développement ou en test) avec EnableDetailedErrors. Les messages d’exception ne doivent pas être exposés au client dans les applications de production.

Gestion des tampons

SignalR utilise des mémoires tampons par connexion pour gérer les messages entrants et sortants. Par défaut, SignalR limite ces mémoires tampons à 32 Ko. Le plus grand message qu’un client ou un serveur peut envoyer est de 32 Ko. La mémoire maximale consommée par une connexion pour les messages est de 32 Ko. Si vos messages sont toujours inférieurs à 32 Ko, vous pouvez réduire la limite, ce qui :

  • Empêche un client de pouvoir envoyer un message plus volumineux.
  • Le serveur n’aura jamais besoin d’allouer de mémoires tampons volumineuses pour accepter les messages.

Si la taille de vos messages est supérieure à 32 Ko, vous pouvez augmenter la limite. L’augmentation de cette limite signifie :

  • Le client peut amener le serveur à allouer des mémoires tampons volumineuses.
  • L’allocation par serveur de mémoires tampons volumineuses peut réduire le nombre de connexions simultanées.

Il existe des limites pour les messages entrants et sortants. Les deux peuvent être configurés sur l’objet HttpConnectionDispatcherOptions configuré dans MapHub :

  • ApplicationMaxBufferSize représente le nombre maximal d’octets du client que le serveur met en mémoire tampon. Si le client tente d’envoyer un message supérieur à cette limite, la connexion peut être fermée.
  • TransportMaxBufferSize représente le nombre maximal d’octets que le serveur peut envoyer. Si le serveur tente d’envoyer un message (y compris les valeurs de retour des méthodes hub) supérieur à cette limite, une exception est levée.

La définition de la limite sur 0 désactive la limite. La suppression de la limite permet à un client d’envoyer un message de toute taille. Les clients malveillants qui envoient des messages volumineux peuvent entraîner l’allocation de mémoire excédentaire. L’utilisation excessive de la mémoire peut réduire considérablement le nombre de connexions simultanées.