如何使需要授权的SignalR集线器荣登登录/注销?

时间:2018-05-21 10:47:54

标签: asp.net-core signalr authorize-attribute asp.net-core-signalr asp.net-core-2.1

我在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();
}

1 个答案:

答案 0 :(得分:2)

在websocket中,仅发送凭证以建立连接,并且不包括在每个帧中。因此,一旦建立了连接,信号器就无法知道用户已经注销了。

就像你说当用户注销时你可以打开另一个套接字来向用户注销的所有标签发送信息。

或者您可以通过javascript定期检查cookie,检查用户是否仍然登录,如果不是,则关闭信号连接。

另一种解决方案是使用共享工作者或广播频道在选项卡之间发送消息。