Вопросы безопасности в 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 не использовать учетные данные. Параметр "не использовать учетные данные" следует применять только в случае, если вы полностью уверены, что такие учетные данные, как файлы cookie, не требуются в вашем приложении (файлы 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 или более поздняя, то ConnectionId должны быть сохранены в тайне, а не ConnectionToken. Он ConnectionToken намеренно не обнаруживается в API. Может быть сложно гарантировать, что старые SignalR клиенты не подключаются к серверу, поэтому даже если версия вашего сервера ASP.NET Core — 3.0 или более поздняя, ConnectionId не должен быть доступен.

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

При использовании 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, не требуются в вашем приложении (cookies используются службой приложений 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 или более поздней версии, то ConnectionToken должен быть сохранен в секрете, а не ConnectionId. Он ConnectionToken намеренно не предоставляется ни в одном API. Может быть трудно убедиться, что старые SignalR клиенты не подключаются к серверу, поэтому даже если SignalR версия сервера ASP.NET Core 3.0 или более поздняя, ConnectionId не должна быть выставлена.

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

При использовании 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% уверены, что такие учетные данные, как файлы cookie, не нужны в вашем приложении (служба приложений Azure использует файлы cookie при работе нескольких серверов для организации липких сеансов).

Например, следующая выделенная политика 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 или выше, то ConnectionToken должен храниться в тайне, а не ConnectionId. Он ConnectionToken намеренно не предоставляется ни в одном API. Может быть сложно убедиться, что старые SignalR клиенты не подключаются к серверу, поэтому, даже если версия вашего сервера — это ASP.NET Core 3.0 или более поздняя, ConnectionId не должна быть раскрыта.

Логирование токенов доступа

При использовании 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 не использовать учетные данные. Параметр "не использовать учетные данные" следует применять только в случае, если вы полностью уверены, что такие учетные данные, как файлы cookie, не требуются в вашем приложении (файлы 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 или более поздняя, то ConnectionId должны быть сохранены в тайне, а не ConnectionToken. Он ConnectionToken намеренно не обнаруживается в API. Может быть сложно гарантировать, что старые SignalR клиенты не подключаются к серверу, поэтому даже если версия вашего сервера ASP.NET Core — 3.0 или более поздняя, ConnectionId не должен быть доступен.

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

При использовании 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 отключает ограничение. Удаление ограничения позволяет клиенту отправлять сообщение любого размера. Вредоносные клиенты могут вызывать выделение избыточной памяти, отправляя большие сообщения. Избыточное использование памяти может значительно сократить количество одновременных подключений.