如何使需要授权的 SignalR 中心登录/注销?
How to make SignalR hubs that require authorization honor loggin in / logging out?
我在 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();
}
在 websocket 中,凭据仅用于建立连接,并不包含在每个帧中。因此,一旦建立连接,signalr 就无法知道用户已注销。
就像您说的那样,当用户注销时,您可以打开另一个套接字向用户已注销的所有选项卡发送消息。
或者您可以通过 javascript 定期检查 cookie 以检查用户是否仍在登录,如果他没有登录则关闭信号器连接。
另一种解决方案是使用 Shared Worker 或广播频道在选项卡之间发送消息。
我在 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();
}
在 websocket 中,凭据仅用于建立连接,并不包含在每个帧中。因此,一旦建立连接,signalr 就无法知道用户已注销。
就像您说的那样,当用户注销时,您可以打开另一个套接字向用户已注销的所有选项卡发送消息。
或者您可以通过 javascript 定期检查 cookie 以检查用户是否仍在登录,如果他没有登录则关闭信号器连接。
另一种解决方案是使用 Shared Worker 或广播频道在选项卡之间发送消息。