Вопросы безопасности в ASP.NET Core SignalR

Эшли Стэнтон-Медсестра

В этой статье содержатся сведения о защите SignalR.

Общий доступ к ресурсам независимо от источник

Кросс-доменный доступ к ресурсам (CORS) используется для разрешения кросс-доменных подключений SignalR в браузере. Если код JavaScript размещен на другом домене, чем приложениеSignalR, необходимо включить промежуточное ПО CORS, чтобы разрешить JavaScript подключаться к приложению SignalR. Разрешать междоменные запросы только из доменов, которым вы доверяете или которые контролируете. Например:

  • Сайт размещен в http://www.example.com
  • Приложение SignalR размещено в http://signalr.example.com

CORS следует настроить в SignalR приложении, чтобы разрешить только источник www.example.com.

Дополнительные сведения о настройке CORS см. в разделе "Включение запросов между источниками" (CORS). SignalR требует следующих политик CORS:

  • Разрешить конкретные ожидаемые источники. Разрешение любого источника возможно, но не безопасно и не рекомендуется.
  • Методы HTTP GET и POST должны быть разрешены.
  • Учетные данные нужно разрешить, чтобы сеансы на основе cookie работали корректно. Они должны быть включены, даже если проверка подлинности не используется.

Однако в версии 5.0 мы предоставили возможность в клиенте TypeScript не использовать учетные данные. Параметр не использовать учетные данные следует использовать только в том случае, если вы знаете 100%, что учетные данные, такие как Cookies не нужны в приложении (файлы cookie используются службой приложений Azure при использовании нескольких серверов для липких сеансов).

Например, следующая выделенная политика CORS позволяет SignalR клиенту браузера, размещенного на https://example.com сайте, получить доступ к SignalR приложению, размещенном в 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");

В предыдущем примере политика CORS настраивается для разрешения определенных источников, методов и учетных данных. Дополнительные сведения о настройке политик CORS и ПО промежуточного слоя в ASP.NET Core см. в разделе ПО промежуточного слоя CORS: CORS с именованной политикой и ПО промежуточного слоя.

Применение политики CORS к SignalR конечным точкам концентратора

Вместо глобального применения политики CORS с помощью промежуточного UseCors слоя можно применять CORS специально к конечным точкам SignalR. Этот подход позволяет устанавливать разные политики CORS для разных частей приложения.

Существует два способа применения политики CORS к SignalR узлам: связывание RequireCors в сопоставлении конечной точки или добавление атрибута [EnableCors] в класс узла. Оба подхода требуют регистрации именованной политики CORS в конфигурации службы. В следующем примере определяется политика с именем "SignalRPolicy":

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

Примените политику CORS к сопоставлению конечных точек концентратора, используя RequireCors в цепочке вызовов MapHub:

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

Примените политику CORS к классу Концентратора[EnableCors], добавив атрибут:

[EnableCors("SignalRPolicy")]
public class ChatHub : Hub
{
    // ...
}

Дополнительные сведения о включении CORS с маршрутизацией конечных точек см. в статье "Включение CORS" с маршрутизацией конечных точек.

Ограничение происхождения WebSocket

Варианты защиты, предоставляемые CORS, не применяются к WebSocket. Для ограничения источника WebSockets ознакомьтесь со статьей Ограничения источника WebSockets.

ConnectionId

Обнаружение ConnectionId может привести к злонамеренному олицетворению, если сервер SignalR или версия клиента ASP.NET Core 2.2 или более ранняя. Если версия сервера и клиента ASP.NET Core 3.0 или более поздняя, то SignalR должны быть сохранены в тайне, а не ConnectionToken. Он ConnectionToken намеренно не обнаруживается в API. Может быть сложно гарантировать, что старые SignalR клиенты не подключаются к серверу, поэтому даже если версия вашего сервера ASP.NET Core — 3.0 или более поздняя, SignalR не должен быть доступен.

Ведение журнала токенов доступа

При использовании WebSockets или событий, отправленных сервером, клиент браузера отправляет маркер доступа в строке запроса. Получение токена доступа через строку запроса обычно так же безопасно, как и с использованием стандартного Authorization заголовка. Всегда используйте ПРОТОКОЛ HTTPS для обеспечения безопасного сквозного подключения между клиентом и сервером. Многие веб-серверы регистрируют URL-адрес для каждого запроса, включая строку запроса. Ведение журнала URL-адресов может привести к записи маркера доступа. ASP.NET Core регистрирует URL-адрес для каждого запроса по умолчанию, который включает строку запроса. Например:

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

Если у вас возникли проблемы с ведением журнала этих данных с помощью журналов сервера, вы можете полностью отключить это ведение журнала, настроив Microsoft.AspNetCore.Hosting средство ведения журнала на Warning уровень или выше (эти сообщения записываются на Info уровне). Дополнительные сведения см. в разделе "Применение правил фильтрации журналов" в коде. Если вы хотите записать определённую информацию о запросе, можно написать промежуточное программное обеспечение, чтобы зафиксировать необходимые данные и отфильтровать access_token значение строки запроса (если оно присутствует).

Исключения

Сообщения об исключениях, как правило, считаются конфиденциальными данными, которые не следует раскрывать клиенту. По умолчанию SignalR не отправляет сведения об исключении, вызванном методом концентратора клиенту. Вместо этого клиент получает общее сообщение с указанием произошедшей ошибки. Доставку сообщений исключений клиенту можно переопределить (например, в разработке или тестировании) с помощью EnableDetailedErrors. Сообщения об исключениях не должны предоставляться клиенту в рабочих приложениях.

Управление буферами

SignalR использует буферы для каждого подключения для управления входящими и исходящими сообщениями. По умолчанию SignalR эти буферы ограничиваются 32 КБ. Наибольшее сообщение, которое может отправлять клиент или сервер, составляет 32 КБ. Максимальный объем памяти, потребляемой подключением для сообщений, составляет 32 КБ. Если ваши сообщения всегда меньше 32 КБ, можно уменьшить ограничение, которое:

  • Запрещает клиенту отправлять большее сообщение.
  • Сервер никогда не должен выделять большие буферы для приема сообщений.

Если ваши сообщения больше 32 КБ, можно увеличить ограничение. Увеличение этого ограничения означает:

  • Клиент может привести к тому, что сервер выделяет большие буферы памяти.
  • Выделение сервера больших буферов может уменьшить количество одновременных подключений.

Существуют ограничения для входящих и исходящих сообщений, их можно настроить в объекте HttpConnectionDispatcherOptions , настроенном в MapHub:

  • ApplicationMaxBufferSize представляет максимальное количество байтов от клиента, которое буферизирует сервер. Если клиент пытается отправить сообщение, превышающее это ограничение, подключение может быть закрыто.
  • TransportMaxBufferSize представляет максимальное количество байтов, которые сервер может отправлять. Если сервер пытается отправить сообщение (включая возвращаемые значения из методов концентратора), больше этого ограничения, будет выброшено исключение.

Установка значения 0 отключает ограничение. Удаление ограничения позволяет клиенту отправлять сообщение любого размера. Вредоносные клиенты, отправляя большие сообщения, могут вызвать выделение избыточной памяти. Избыточное использование памяти может значительно сократить количество одновременных подключений.

В этой статье содержатся сведения о защите SignalR.

Общий доступ к ресурсам независимо от источник

Кросс-доменный доступ к ресурсам (CORS) используется для разрешения кросс-доменных подключений SignalR в браузере. Если код JavaScript размещен на другом домене, чем приложениеSignalR, необходимо включить промежуточное ПО CORS, чтобы разрешить JavaScript подключаться к приложению SignalR. Разрешать междоменные запросы только из доменов, которым вы доверяете или которые контролируете. Например:

  • Сайт размещен в http://www.example.com
  • Приложение SignalR размещено в http://signalr.example.com

CORS следует настроить в SignalR приложении, чтобы разрешить только источник www.example.com.

Дополнительные сведения о настройке CORS см. в разделе "Включение запросов между источниками" (CORS). SignalR требует следующих политик CORS:

  • Разрешить конкретные ожидаемые источники. Разрешение любого источника возможно, но не безопасно и не рекомендуется.
  • Методы HTTP GET и POST должны быть разрешены.
  • Учетные данные нужно разрешить, чтобы сеансы на основе cookie работали корректно. Они должны быть включены, даже если проверка подлинности не используется.

Однако в версии 5.0 мы предоставили возможность в клиенте TypeScript не использовать учетные данные. Параметр не использовать учетные данные следует использовать только в том случае, если вы знаете 100%, что учетные данные, такие как Cookies не нужны в приложении (файлы cookie используются службой приложений Azure при использовании нескольких серверов для липких сеансов).

Например, следующая выделенная политика CORS позволяет SignalR клиенту браузера, размещенного на https://example.com сайте, получить доступ к SignalR приложению, размещенном в 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");

В предыдущем примере политика CORS настраивается для разрешения определенных источников, методов и учетных данных. Дополнительные сведения о настройке политик CORS и ПО промежуточного слоя в ASP.NET Core см. в разделе ПО промежуточного слоя CORS: CORS с именованной политикой и ПО промежуточного слоя.

Ограничение происхождения WebSocket

Варианты защиты, предоставляемые CORS, не применяются к WebSocket. Для ограничения источника WebSockets ознакомьтесь со статьей Ограничения источника WebSockets.

ConnectionId

Обнаружение ConnectionId может привести к злонамеренному олицетворению, если сервер SignalR или версия клиента ASP.NET Core 2.2 или более ранняя. Если версия сервера и клиента ASP.NET Core 3.0 или более поздняя, то SignalR должны быть сохранены в тайне, а не ConnectionToken. Он ConnectionToken намеренно не обнаруживается в API. Может быть сложно гарантировать, что старые SignalR клиенты не подключаются к серверу, поэтому даже если версия вашего сервера ASP.NET Core — 3.0 или более поздняя, SignalR не должен быть доступен.

Ведение журнала токенов доступа

При использовании WebSockets или событий, отправленных сервером, клиент браузера отправляет маркер доступа в строке запроса. Получение токена доступа через строку запроса обычно так же безопасно, как и с использованием стандартного Authorization заголовка. Всегда используйте ПРОТОКОЛ HTTPS для обеспечения безопасного сквозного подключения между клиентом и сервером. Многие веб-серверы регистрируют URL-адрес для каждого запроса, включая строку запроса. Ведение журнала URL-адресов может привести к записи маркера доступа. ASP.NET Core регистрирует URL-адрес для каждого запроса по умолчанию, который включает строку запроса. Например:

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

Если у вас возникли проблемы с ведением журнала этих данных с помощью журналов сервера, вы можете полностью отключить это ведение журнала, настроив Microsoft.AspNetCore.Hosting средство ведения журнала на Warning уровень или выше (эти сообщения записываются на Info уровне). Дополнительные сведения см. в разделе "Применение правил фильтрации журналов" в коде. Если вы хотите записать определённую информацию о запросе, можно написать промежуточное программное обеспечение, чтобы зафиксировать необходимые данные и отфильтровать access_token значение строки запроса (если оно присутствует).

Исключения

Сообщения об исключениях, как правило, считаются конфиденциальными данными, которые не следует раскрывать клиенту. По умолчанию SignalR не отправляет сведения об исключении, вызванном методом концентратора клиенту. Вместо этого клиент получает общее сообщение с указанием произошедшей ошибки. Доставку сообщений исключений клиенту можно переопределить (например, в разработке или тестировании) с помощью EnableDetailedErrors. Сообщения об исключениях не должны предоставляться клиенту в рабочих приложениях.

Управление буферами

SignalR использует буферы для каждого подключения для управления входящими и исходящими сообщениями. По умолчанию SignalR эти буферы ограничиваются 32 КБ. Наибольшее сообщение, которое может отправлять клиент или сервер, составляет 32 КБ. Максимальный объем памяти, потребляемой подключением для сообщений, составляет 32 КБ. Если ваши сообщения всегда меньше 32 КБ, можно уменьшить ограничение, которое:

  • Запрещает клиенту отправлять большее сообщение.
  • Сервер никогда не должен выделять большие буферы для приема сообщений.

Если ваши сообщения больше 32 КБ, можно увеличить ограничение. Увеличение этого ограничения означает:

  • Клиент может привести к тому, что сервер выделяет большие буферы памяти.
  • Выделение сервера больших буферов может уменьшить количество одновременных подключений.

Существуют ограничения для входящих и исходящих сообщений, их можно настроить в объекте HttpConnectionDispatcherOptions , настроенном в MapHub:

  • ApplicationMaxBufferSize представляет максимальное количество байтов от клиента, которое буферизирует сервер. Если клиент пытается отправить сообщение, превышающее это ограничение, подключение может быть закрыто.
  • TransportMaxBufferSize представляет максимальное количество байтов, которые сервер может отправлять. Если сервер пытается отправить сообщение (включая возвращаемые значения из методов концентратора), больше этого ограничения, будет выброшено исключение.

Установка значения 0 отключает ограничение. Удаление ограничения позволяет клиенту отправлять сообщение любого размера. Вредоносные клиенты, отправляя большие сообщения, могут вызвать выделение избыточной памяти. Избыточное использование памяти может значительно сократить количество одновременных подключений.

В этой статье содержатся сведения о защите SignalR.

Общий доступ к ресурсам независимо от источник

Кросс-доменный доступ к ресурсам (CORS) используется для разрешения кросс-доменных подключений SignalR в браузере. Если код JavaScript размещен на другом домене, чем приложениеSignalR, необходимо включить промежуточное ПО CORS, чтобы разрешить JavaScript подключаться к приложению SignalR. Разрешать междоменные запросы только из доменов, которым вы доверяете или которые контролируете. Например:

  • Сайт размещен в http://www.example.com
  • Приложение SignalR размещено в http://signalr.example.com

CORS следует настроить в SignalR приложении, чтобы разрешить только источник www.example.com.

Дополнительные сведения о настройке CORS см. в разделе "Включение запросов между источниками" (CORS). SignalR требует следующих политик CORS:

  • Разрешить конкретные ожидаемые источники. Разрешение любого источника возможно, но не безопасно и не рекомендуется.
  • Методы HTTP GET и POST должны быть разрешены.
  • Учетные данные нужно разрешить, чтобы сеансы на основе cookie работали корректно. Они должны быть включены, даже если проверка подлинности не используется.

Однако в версии 5.0 мы предоставили возможность в клиенте TypeScript не использовать учетные данные. Параметр не использовать учетные данные следует использовать только в том случае, если вы знаете 100%, что учетные данные, такие как Cookies не нужны в приложении (файлы cookie используются службой приложений Azure при использовании нескольких серверов для липких сеансов).

Например, следующая выделенная политика CORS позволяет SignalR клиенту браузера, размещенного на https://example.com сайте, получить доступ к SignalR приложению, размещенном в 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");

В предыдущем примере политика CORS настраивается для разрешения определенных источников, методов и учетных данных. Дополнительные сведения о настройке политик CORS и ПО промежуточного слоя в ASP.NET Core см. в разделе ПО промежуточного слоя CORS: CORS с именованной политикой и ПО промежуточного слоя.

Ограничение происхождения WebSocket

Варианты защиты, предоставляемые CORS, не применяются к WebSocket. Для ограничения источника WebSockets ознакомьтесь со статьей Ограничения источника WebSockets.

ConnectionId

Обнаружение ConnectionId может привести к злонамеренному олицетворению, если сервер SignalR или версия клиента ASP.NET Core 2.2 или более ранняя. Если версия сервера и клиента ASP.NET Core 3.0 или более поздняя, то SignalR должны быть сохранены в тайне, а не ConnectionToken. Он ConnectionToken намеренно не обнаруживается в API. Может быть сложно гарантировать, что старые SignalR клиенты не подключаются к серверу, поэтому даже если версия вашего сервера ASP.NET Core — 3.0 или более поздняя, SignalR не должен быть доступен.

Ведение журнала токенов доступа

При использовании WebSockets или событий, отправленных сервером, клиент браузера отправляет маркер доступа в строке запроса. Получение токена доступа через строку запроса обычно так же безопасно, как и с использованием стандартного Authorization заголовка. Всегда используйте ПРОТОКОЛ HTTPS для обеспечения безопасного сквозного подключения между клиентом и сервером. Многие веб-серверы регистрируют URL-адрес для каждого запроса, включая строку запроса. Ведение журнала URL-адресов может привести к записи маркера доступа. ASP.NET Core регистрирует URL-адрес для каждого запроса по умолчанию, который включает строку запроса. Например:

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

Если у вас возникли проблемы с ведением журнала этих данных с помощью журналов сервера, вы можете полностью отключить это ведение журнала, настроив Microsoft.AspNetCore.Hosting средство ведения журнала на Warning уровень или выше (эти сообщения записываются на Info уровне). Дополнительные сведения см. в разделе "Применение правил фильтрации журналов" в коде. Если вы хотите записать определённую информацию о запросе, можно написать промежуточное программное обеспечение, чтобы зафиксировать необходимые данные и отфильтровать access_token значение строки запроса (если оно присутствует).

Исключения

Сообщения об исключениях, как правило, считаются конфиденциальными данными, которые не следует раскрывать клиенту. По умолчанию SignalR не отправляет сведения об исключении, вызванном методом концентратора клиенту. Вместо этого клиент получает общее сообщение с указанием произошедшей ошибки. Доставку сообщений исключений клиенту можно переопределить (например, в разработке или тестировании) с помощью EnableDetailedErrors. Сообщения об исключениях не должны предоставляться клиенту в рабочих приложениях.

Управление буферами

SignalR использует буферы для каждого подключения для управления входящими и исходящими сообщениями. По умолчанию SignalR эти буферы ограничиваются 32 КБ. Наибольшее сообщение, которое может отправлять клиент или сервер, составляет 32 КБ. Максимальный объем памяти, потребляемой подключением для сообщений, составляет 32 КБ. Если ваши сообщения всегда меньше 32 КБ, можно уменьшить ограничение, которое:

  • Запрещает клиенту отправлять большее сообщение.
  • Сервер никогда не должен выделять большие буферы для приема сообщений.

Если ваши сообщения больше 32 КБ, можно увеличить ограничение. Увеличение этого ограничения означает:

  • Клиент может привести к тому, что сервер выделяет большие буферы памяти.
  • Выделение сервера больших буферов может уменьшить количество одновременных подключений.

Существуют ограничения для входящих и исходящих сообщений, их можно настроить в объекте HttpConnectionDispatcherOptions , настроенном в MapHub:

  • ApplicationMaxBufferSize представляет максимальное количество байтов от клиента, которое буферизирует сервер. Если клиент пытается отправить сообщение, превышающее это ограничение, подключение может быть закрыто.
  • TransportMaxBufferSize представляет максимальное количество байтов, которые сервер может отправлять. Если сервер пытается отправить сообщение (включая возвращаемые значения из методов концентратора), больше этого ограничения, будет выброшено исключение.

Установка значения 0 отключает ограничение. Удаление ограничения позволяет клиенту отправлять сообщение любого размера. Вредоносные клиенты, отправляя большие сообщения, могут вызвать выделение избыточной памяти. Избыточное использование памяти может значительно сократить количество одновременных подключений.

В этой статье содержатся сведения о защите SignalR.

Общий доступ к ресурсам независимо от источник

Кросс-доменный доступ к ресурсам (CORS) используется для разрешения кросс-доменных подключений SignalR в браузере. Если код JavaScript размещен на другом домене, чем приложениеSignalR, необходимо включить промежуточное ПО CORS, чтобы разрешить JavaScript подключаться к приложению SignalR. Разрешать междоменные запросы только из доменов, которым вы доверяете или которые контролируете. Например:

  • Сайт размещен в http://www.example.com
  • Приложение SignalR размещено в http://signalr.example.com

CORS следует настроить в SignalR приложении, чтобы разрешить только источник www.example.com.

Дополнительные сведения о настройке CORS см. в разделе "Включение запросов между источниками" (CORS). SignalR требует следующих политик CORS:

  • Разрешить конкретные ожидаемые источники. Разрешение любого источника возможно, но не безопасно и не рекомендуется.
  • Методы HTTP GET и POST должны быть разрешены.
  • Учетные данные нужно разрешить, чтобы сеансы на основе cookie работали корректно. Они должны быть включены, даже если проверка подлинности не используется.

Однако в версии 5.0 мы предоставили возможность в клиенте TypeScript не использовать учетные данные. Параметр не использовать учетные данные следует использовать только в том случае, если вы знаете 100%, что учетные данные, такие как Cookies не нужны в приложении (файлы cookie используются службой приложений Azure при использовании нескольких серверов для липких сеансов).

Например, следующая политика CORS позволяет SignalR клиенту браузера, размещенного на https://example.com сайте, получить доступ к SignalR приложению, размещенного в 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 ...
}

Ограничение происхождения WebSocket

Варианты защиты, предоставляемые CORS, не применяются к WebSocket. Для ограничения источника WebSockets ознакомьтесь со статьей Ограничения источника WebSockets.

Варианты защиты, предоставляемые CORS, не применяются к WebSocket. Браузеры не:

  • Выполняйте предварительные запросы CORS.
  • Соблюдайте ограничения, указанные в заголовках Access-Control, при выполнении запросов WebSocket.

Однако браузеры отправляют заголовок Origin при выпуске запросов WebSocket. Приложения должны быть настроены на проверку этих заголовков, чтобы в них допускались только WebSockets из ожидаемых источников.

В ASP.NET Core 2.1 или более поздней версии проверка заголовков может быть выполнена с помощью пользовательского примеси, размещенного перед UseSignalR, и примеси проверки подлинности в 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 ...
}

Примечание.

Заголовок Origin контролируется клиентом и, как и заголовок Referer, может быть подделан. Эти заголовки не должны использоваться в качестве механизма проверки подлинности.

ConnectionId

Обнаружение ConnectionId может привести к злонамеренному олицетворению, если сервер SignalR или версия клиента ASP.NET Core 2.2 или более ранняя. Если версия сервера и клиента ASP.NET Core 3.0 или более поздняя, то SignalR должны быть сохранены в тайне, а не ConnectionToken. Он ConnectionToken намеренно не обнаруживается в API. Может быть сложно гарантировать, что старые SignalR клиенты не подключаются к серверу, поэтому даже если версия вашего сервера ASP.NET Core — 3.0 или более поздняя, SignalR не должен быть доступен.

Ведение журнала токенов доступа

При использовании WebSockets или событий, отправленных сервером, клиент браузера отправляет маркер доступа в строке запроса. Получение токена доступа через строку запроса обычно так же безопасно, как и с использованием стандартного Authorization заголовка. Всегда используйте ПРОТОКОЛ HTTPS для обеспечения безопасного сквозного подключения между клиентом и сервером. Многие веб-серверы регистрируют URL-адрес для каждого запроса, включая строку запроса. Ведение журнала URL-адресов может привести к записи маркера доступа. ASP.NET Core регистрирует URL-адрес для каждого запроса по умолчанию, который включает строку запроса. Например:

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

Если у вас возникли проблемы с ведением журнала этих данных с помощью журналов сервера, вы можете полностью отключить это ведение журнала, настроив Microsoft.AspNetCore.Hosting средство ведения журнала на Warning уровень или выше (эти сообщения записываются на Info уровне). Дополнительные сведения см. в разделе "Применение правил фильтрации журналов" в коде. Если вы хотите записать определённую информацию о запросе, можно написать промежуточное программное обеспечение, чтобы зафиксировать необходимые данные и отфильтровать access_token значение строки запроса (если оно присутствует).

Исключения

Сообщения об исключениях, как правило, считаются конфиденциальными данными, которые не следует раскрывать клиенту. По умолчанию SignalR не отправляет сведения об исключении, вызванном методом концентратора клиенту. Вместо этого клиент получает общее сообщение с указанием произошедшей ошибки. Доставку сообщений исключений клиенту можно переопределить (например, в разработке или тестировании) с помощью EnableDetailedErrors. Сообщения об исключениях не должны предоставляться клиенту в рабочих приложениях.

Управление буферами

SignalR использует буферы для каждого подключения для управления входящими и исходящими сообщениями. По умолчанию SignalR эти буферы ограничиваются 32 КБ. Наибольшее сообщение, которое может отправлять клиент или сервер, составляет 32 КБ. Максимальный объем памяти, потребляемой подключением для сообщений, составляет 32 КБ. Если ваши сообщения всегда меньше 32 КБ, можно уменьшить ограничение, которое:

  • Запрещает клиенту отправлять большее сообщение.
  • Сервер никогда не должен выделять большие буферы для приема сообщений.

Если ваши сообщения больше 32 КБ, можно увеличить ограничение. Увеличение этого ограничения означает:

  • Клиент может привести к тому, что сервер выделяет большие буферы памяти.
  • Выделение сервера больших буферов может уменьшить количество одновременных подключений.

Существуют ограничения для входящих и исходящих сообщений, их можно настроить в объекте HttpConnectionDispatcherOptions , настроенном в MapHub:

  • ApplicationMaxBufferSize представляет максимальное количество байтов от клиента, которое буферизирует сервер. Если клиент пытается отправить сообщение, превышающее это ограничение, подключение может быть закрыто.
  • TransportMaxBufferSize представляет максимальное количество байтов, которые сервер может отправлять. Если сервер пытается отправить сообщение (включая возвращаемые значения из методов концентратора), больше этого ограничения, будет выброшено исключение.

Установка значения 0 отключает ограничение. Удаление ограничения позволяет клиенту отправлять сообщение любого размера. Вредоносные клиенты, отправляя большие сообщения, могут вызвать выделение избыточной памяти. Избыточное использование памяти может значительно сократить количество одновременных подключений.