Как сделать так, чтобы концентраторы SignalR, требующие авторизации, учитывали вход/выход из системы?

У меня есть простая реализация чата в SignalR. Все могут читать то, что печатают другие, но только зарегистрированные пользователи могут говорить:

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;

namespace WebApplication1.Hubs
{
    public class ChatHub : Hub
    {
        [Authorize]
        public async Task SendMessage(string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", Context.User.Identity.Name, message);
        }
    }
}

И это работает. За исключением... Когда у пользователя открыт чат в одной вкладке, но он входит/выходит из системы в другой вкладке.

  • Когда пользователь выходит из системы на другой вкладке, он по-прежнему может свободно говорить в чате. Чат отправляет их сообщения с их никнеймом, который у них был до выхода из системы. Это сохраняется до тех пор, пока вкладка чата не будет перезагружена.
  • Когда пользователь не вошел в систему, но по-прежнему открывает чат на одной вкладке, а затем входит в систему на другой вкладке, он может не говорить в чате, пока не перезагрузит вкладку чата.

Почему, несмотря на наличие атрибута [Authorize], метод SendMessage продолжает работать, даже если пользователь больше не аутентифицирован?

Как это исправить? Как заставить мой чат-хаб следовать аутентификации, которая происходит после подключения клиента?

ASP .NET Core 2.1 RC1, так как 2.0 не поддерживает SignalR.

РЕДАКТИРОВАТЬ: Согласно запросу из комментариев, Startup.Configure:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();
    app.UseAuthentication();

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

    app.UseMvc();
}

person Community    schedule 21.05.2018    source источник
comment
Покажите свой Startup.Configure метод.   -  person aaron    schedule 21.05.2018
comment
@aaron Смотрите отредактированный пост.   -  person    schedule 21.05.2018
comment
Используете ли вы файлы cookie? Если да, то это проблема.   -  person davidfowl    schedule 21.05.2018
comment
@davidfowl Использую ли я файлы cookie? Я думал, что Identity должна использовать файлы cookie. Итак, как мне разрешить пользователям входить/выходить из системы, если не с помощью файлов cookie? В любом случае, почему это важно? В моей мысленной модели выход из системы должен очищать файлы cookie, связанные с аутентификацией, поэтому они не должны отправляться, когда клиент вызывает методы концентратора, поэтому атрибут Authorize должен обнаруживать, что эти файлы cookie не отправляются, и блокировать запрос. Моя ментальная модель неверна?   -  person    schedule 21.05.2018
comment
@davidfowl Чтобы было понятно, что используется, а что нет. Я воспроизвел эту проблему в пустом проекте Razor pages с включенной проверкой подлинности. Единственное, что я сделал, — это добавил рабочий пример страницы чата SignalR в соответствии с это руководство docs.microsoft.com. Я отклонился от этого руководства только для того, чтобы включить поддержку учетных записей: вы можете увидеть полученный концентратор SignalR выше.   -  person    schedule 21.05.2018
comment
Учетные данные в веб-сокетах отправляются только для установления соединения и не включаются в каждый кадр. Таким образом, как только соединение установлено, сигнализатор не может узнать, что пользователь вышел из системы.   -  person J.Loscos    schedule 24.05.2018
comment
@ J.Loscos, сделай ответ, и я отмечу его принятым. Итак, я думаю, мне нужно создать еще один канал сокета, который будет отправлять на все вкладки информацию о том, что пользователь вошел/вышел из системы, и что им нужно перезапустить другие соединения?   -  person    schedule 24.05.2018


Ответы (1)


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

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

Или вы можете периодически проверять файлы cookie с помощью javascript, чтобы убедиться, что пользователь все еще входит в систему, и закрыть соединение с сигнализатором, если он этого не делает.

Другим решением было бы использовать общий рабочий или широковещательный канал для отправки сообщений между вкладками.

person J.Loscos    schedule 24.05.2018
comment
Периодическая проверка файлов cookie не будет работать — файлы cookie, доступные концентратору, — это файлы cookie, когда веб-сокет был впервые установлен. - person thab; 30.05.2018