网站首页 网站源码
using Dpz.Core.Web.Library.Api;
using Dpz.Core.Web.Models;
using Microsoft.AspNetCore.Authorization;
namespace Dpz.Core.Web.Library.Hub;
public class ChatHub(
IChatRecordService chatRecordService,
IAccountService accountService,
IChatCurrentUserService chatCurrentUserService
) : Microsoft.AspNetCore.SignalR.Hub
{
[Authorize]
public async Task SendMessageToUser(string user, string message)
{
if (Context.User == null)
{
return;
}
var sender = Context.User.GetIdentity();
if (sender == null)
{
return;
}
await Clients
.User(user)
.SendCoreAsync(
"ReceiveMessage",
[ReceiveContent.ToReceiveContent(sender, message)]
);
#region save record
var receiver = await accountService.GetOneUserAsync(user);
await chatRecordService.SaveFriendRecordAsync(sender, message, receiver);
#endregion
}
[Authorize]
public async Task SendMessageToGroup(string groupId, string message)
{
if (Context.User == null)
{
return;
}
var sender = Context.User.GetIdentity();
if (sender == null)
{
return;
}
var userInfo = Context.User.GetStrictIdentity();
List<VmUserInfo> users;
if (groupId == WebToolsExtensions.DefaultGroupId)
{
var list = await accountService.GetPageAsync(1, 100, userInfo.Id);
users = [..list];
}
else
{
users = new List<VmUserInfo>();
}
await Clients
.Users(users.Select(x => x.Id).ToList())
.SendCoreAsync(
"ReceiveMessage",
[ReceiveContent.ToGroupContent(groupId, userInfo, message)]
);
#region save record
await chatRecordService.SaveGroupRecordAsync(sender, groupId, message);
#endregion
}
public override async Task OnConnectedAsync()
{
if (Context.User == null || !Context.User.IsLogin())
{
await Clients.Caller.SendCoreAsync(
"System",
[
new
{
code = -1,
system = true,
id = "00000",
content = "没有登录"
}
]
);
return;
}
var currentUser = Context.User.GetIdentity();
if (currentUser == null)
{
return;
}
await chatCurrentUserService.AddAsync(Context.ConnectionId, currentUser);
await Clients.Others.SendCoreAsync(
"System",
[
new
{
code = 1,
system = true,
isGuest = false,
user = currentUser
}
]
);
await base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception? exception)
{
if (Context.User.IsLogin())
{
await chatCurrentUserService.RemoveAsync(Context.ConnectionId);
}
await Clients.Others.SendCoreAsync(
"System",
[
new
{
code = 0,
system = true,
isGuest = Context.User?.Identity?.IsAuthenticated != true,
user = Context.User?.Identity?.IsAuthenticated == true
? Context.User.GetIdentity()
: null
}
]
);
await base.OnDisconnectedAsync(exception);
}
}
//public class DomainRestrictedRequirement :
// AuthorizationHandler<DomainRestrictedRequirement, HubInvocationContext>,
// IAuthorizationRequirement
//{
// protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
// DomainRestrictedRequirement requirement,
// HubInvocationContext resource)
// {
// if (IsUserAllowedToDoThis(resource.HubMethodName, context.User.Identity.Name) &&
// context.User.Identity.Name.EndsWith("@microsoft.com"))
// {
// context.Succeed(requirement);
// }
// return Task.CompletedTask;
// }
// private bool IsUserAllowedToDoThis(string hubMethodName,
// string currentUsername)
// {
// return !(currentUsername.Equals("asdf42@microsoft.com") &&
// hubMethodName.Equals("banUser", StringComparison.OrdinalIgnoreCase));
// }
//}
上述代码定义了一个 SignalR Hub 类 ChatHub
,用于处理实时聊天功能。这个 Hub 允许用户之间发送消息,并管理用户的连接和断开连接事件。以下是代码的主要功能和结构的详细解释:
ChatHub
类的构造函数接受三个服务作为参数:
IChatRecordService
:用于保存聊天记录。IAccountService
:用于获取用户信息。IChatCurrentUserService
:用于管理当前在线用户的信息。SendMessageToUser
方法允许已授权的用户向特定用户发送消息。其主要步骤包括:
Clients.User(user)
将消息发送给指定的用户。chatRecordService.SaveFriendRecordAsync
方法。SendMessageToGroup
方法允许已授权的用户向特定组发送消息。其主要步骤包括:
groupId
获取用户列表(如果是默认组,则获取当前用户的好友列表)。Clients.Users(users.Select(x => x.Id).ToList())
将消息发送给组内的所有用户。chatRecordService.SaveGroupRecordAsync
方法。OnConnectedAsync
方法在用户连接到 Hub 时被调用。其主要步骤包括:
OnDisconnectedAsync
方法在用户断开连接时被调用。其主要步骤包括:
注释部分包含一个 DomainRestrictedRequirement
类,用于处理特定的授权逻辑。它检查用户是否有权执行某个 Hub 方法,并且用户的电子邮件是否以 @microsoft.com
结尾。这个部分目前被注释掉,可能是为了将来使用或进行进一步的开发。
整体而言,ChatHub
类实现了一个基本的实时聊天功能,支持用户之间的私信和群组消息发送,同时管理用户的连接状态和聊天记录。通过使用 SignalR,应用程序能够实现实时的双向通信。