feat:添加长连接,强制下线功能
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Yi.Furion.Application.Rbac.Services
|
||||
{
|
||||
public interface IOnlineService
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Yi.Framework.Infrastructure.Ddd.Dtos;
|
||||
using Yi.Furion.Application.Rbac.SignalRHub;
|
||||
using Yi.Furion.Application.Rbac.SignalRHub.Model;
|
||||
|
||||
namespace Yi.Furion.Application.Rbac.Services.Impl
|
||||
{
|
||||
public class OnlineService:IOnlineService,IDynamicApiController,ITransient
|
||||
{
|
||||
private ILogger<OnlineService> _logger;
|
||||
private IHubContext<OnlineUserHub> _hub;
|
||||
public OnlineService(ILogger<OnlineService> logger, IHubContext<OnlineUserHub> hub)
|
||||
{
|
||||
_logger = logger;
|
||||
_hub = hub;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 动态条件获取当前在线用户
|
||||
/// </summary>
|
||||
/// <param name="online"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("")]
|
||||
public PagedResultDto<OnlineUserModel> GetListAsync([FromQuery] OnlineUserModel online)
|
||||
{
|
||||
var data = OnlineUserHub.clientUsers;
|
||||
IEnumerable<OnlineUserModel> dataWhere = data.AsEnumerable();
|
||||
|
||||
if (!string.IsNullOrEmpty(online.Ipaddr))
|
||||
{
|
||||
dataWhere = dataWhere.Where((u) => u.Ipaddr!.Contains(online.Ipaddr));
|
||||
}
|
||||
if (!string.IsNullOrEmpty(online.UserName))
|
||||
{
|
||||
dataWhere = dataWhere.Where((u) => u.UserName!.Contains(online.UserName));
|
||||
}
|
||||
return new PagedResultDto<OnlineUserModel>() { Total = data.Count, Items = dataWhere.ToList() };
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 强制退出用户
|
||||
/// </summary>
|
||||
/// <param name="connnectionId"></param>
|
||||
/// <returns></returns>
|
||||
[HttpDelete]
|
||||
[Route("{connnectionId}")]
|
||||
public async Task<bool> ForceOut(string connnectionId)
|
||||
{
|
||||
if (OnlineUserHub.clientUsers.Exists(u => u.ConnnectionId == connnectionId))
|
||||
{
|
||||
//前端接受到这个事件后,触发前端自动退出
|
||||
await _hub.Clients.Client(connnectionId).SendAsync("forceOut", "你已被强制退出!");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Yi.Furion.Application.Rbac.SignalRHub.Model
|
||||
{
|
||||
public class OnlineUserModel
|
||||
{
|
||||
public OnlineUserModel()
|
||||
{
|
||||
|
||||
}
|
||||
public OnlineUserModel(string connnectionId)
|
||||
{
|
||||
ConnnectionId = connnectionId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 客户端连接Id
|
||||
/// </summary>
|
||||
public string ConnnectionId { get; }
|
||||
/// <summary>
|
||||
/// 用户id
|
||||
/// </summary>
|
||||
public long? UserId { get; set; }
|
||||
public string UserName { get; set; }
|
||||
public DateTime? LoginTime { get; set; }
|
||||
public string Ipaddr { get; set; }
|
||||
public string LoginLocation { get; set; }
|
||||
|
||||
public string Os { get; set; }
|
||||
public string Browser { get; set; }
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using IPTools.Core;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using UAParser;
|
||||
using Yi.Framework.Infrastructure.AspNetCore;
|
||||
using Yi.Framework.Infrastructure.CurrentUsers;
|
||||
using Yi.Furion.Application.Rbac.SignalRHub.Model;
|
||||
using Yi.Furion.Core.Rbac.Entities;
|
||||
|
||||
namespace Yi.Furion.Application.Rbac.SignalRHub
|
||||
{
|
||||
public class OnlineUserHub : Hub
|
||||
{
|
||||
public static readonly List<OnlineUserModel> clientUsers = new();
|
||||
|
||||
|
||||
private HttpContext _httpContext;
|
||||
private ILogger<OnlineUserHub> _logger;
|
||||
private ICurrentUser _currentUser;
|
||||
public OnlineUserHub(IHttpContextAccessor httpContextAccessor, ILogger<OnlineUserHub> logger, ICurrentUser currentUser)
|
||||
{
|
||||
_httpContext = httpContextAccessor.HttpContext;
|
||||
_logger = logger;
|
||||
_currentUser = currentUser;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 成功连接
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override Task OnConnectedAsync()
|
||||
{
|
||||
var name = _currentUser.UserName;
|
||||
var loginUser = GetLoginLogInfo(_httpContext);
|
||||
var user = clientUsers.Any(u => u.ConnnectionId == Context.ConnectionId);
|
||||
//判断用户是否存在,否则添加集合
|
||||
if (!user )
|
||||
{
|
||||
OnlineUserModel users = new(Context.ConnectionId)
|
||||
{
|
||||
Browser = loginUser?.Browser,
|
||||
LoginLocation = loginUser?.LoginLocation,
|
||||
Ipaddr = loginUser?.LoginIp,
|
||||
LoginTime = DateTime.Now,
|
||||
Os = loginUser?.Os,
|
||||
UserName = name ?? ""
|
||||
};
|
||||
clientUsers.Add(users);
|
||||
_logger.LogInformation($"{DateTime.Now}:{name},{Context.ConnectionId}连接服务端success,当前已连接{clientUsers.Count}个");
|
||||
|
||||
//Clients.All.SendAsync(HubsConstant.MoreNotice, SendNotice());
|
||||
}
|
||||
//当有人加入,向全部客户端发送当前总数
|
||||
Clients.All.SendAsync("onlineNum", clientUsers.Count);
|
||||
//Clients.All.SendAsync(HubsConstant.OnlineUser, clientUsers);
|
||||
return base.OnConnectedAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 断开连接
|
||||
/// </summary>
|
||||
/// <param name="exception"></param>
|
||||
/// <returns></returns>
|
||||
public override Task OnDisconnectedAsync(Exception exception)
|
||||
{
|
||||
var user = clientUsers.Where(p => p.ConnnectionId == Context.ConnectionId).FirstOrDefault();
|
||||
//判断用户是否存在,否则添加集合
|
||||
if (user != null)
|
||||
{
|
||||
clientUsers.Remove(user);
|
||||
Clients.All.SendAsync("onlineNum", clientUsers.Count);
|
||||
//Clients.All.SendAsync(HubsConstant.OnlineUser, clientUsers);
|
||||
_logger.LogInformation($"用户{user?.UserName}离开了,当前已连接{clientUsers.Count}个");
|
||||
}
|
||||
return base.OnDisconnectedAsync(exception);
|
||||
}
|
||||
|
||||
public async Task SendAllTest(string test)
|
||||
{
|
||||
await Clients.All.SendAsync("ReceiveAllInfo", test);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取客户端信息
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
private static ClientInfo GetClientInfo(HttpContext context)
|
||||
{
|
||||
var str = context.GetUserAgent();
|
||||
var uaParser = Parser.GetDefault();
|
||||
ClientInfo c = uaParser.Parse(str);
|
||||
return c;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 记录用户登陆信息
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
private static LoginLogEntity GetLoginLogInfo(HttpContext context)
|
||||
{
|
||||
var ipAddr = context.GetClientIp();
|
||||
IpInfo location;
|
||||
if (ipAddr == "127.0.0.1")
|
||||
{
|
||||
location = new IpInfo() { Province = "本地", City = "本机" };
|
||||
}
|
||||
else
|
||||
{
|
||||
location = IpTool.Search(ipAddr);
|
||||
}
|
||||
ClientInfo clientInfo = GetClientInfo(context);
|
||||
LoginLogEntity entity = new()
|
||||
{
|
||||
Browser = clientInfo.Device.Family,
|
||||
Os = clientInfo.OS.ToString(),
|
||||
LoginIp = ipAddr,
|
||||
LoginLocation = location.Province + "-" + location.City
|
||||
};
|
||||
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -418,6 +418,20 @@
|
||||
<param name="roleId"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:Yi.Furion.Application.Rbac.Services.Impl.OnlineService.GetListAsync(Yi.Furion.Application.Rbac.SignalRHub.Model.OnlineUserModel)">
|
||||
<summary>
|
||||
动态条件获取当前在线用户
|
||||
</summary>
|
||||
<param name="online"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:Yi.Furion.Application.Rbac.Services.Impl.OnlineService.ForceOut(System.String)">
|
||||
<summary>
|
||||
强制退出用户
|
||||
</summary>
|
||||
<param name="connnectionId"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:Yi.Furion.Application.Rbac.Services.Impl.PostService">
|
||||
<summary>
|
||||
Post服务实现
|
||||
@@ -516,5 +530,42 @@
|
||||
User服务抽象
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Yi.Furion.Application.Rbac.SignalRHub.Model.OnlineUserModel.ConnnectionId">
|
||||
<summary>
|
||||
客户端连接Id
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Yi.Furion.Application.Rbac.SignalRHub.Model.OnlineUserModel.UserId">
|
||||
<summary>
|
||||
用户id
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Yi.Furion.Application.Rbac.SignalRHub.OnlineUserHub.OnConnectedAsync">
|
||||
<summary>
|
||||
成功连接
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:Yi.Furion.Application.Rbac.SignalRHub.OnlineUserHub.OnDisconnectedAsync(System.Exception)">
|
||||
<summary>
|
||||
断开连接
|
||||
</summary>
|
||||
<param name="exception"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:Yi.Furion.Application.Rbac.SignalRHub.OnlineUserHub.GetClientInfo(Microsoft.AspNetCore.Http.HttpContext)">
|
||||
<summary>
|
||||
获取客户端信息
|
||||
</summary>
|
||||
<param name="context"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:Yi.Furion.Application.Rbac.SignalRHub.OnlineUserHub.GetLoginLogInfo(Microsoft.AspNetCore.Http.HttpContext)">
|
||||
<summary>
|
||||
记录用户登陆信息
|
||||
</summary>
|
||||
<param name="context"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
|
||||
@@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Yi.Framework.Infrastructure.Data.Json;
|
||||
using Yi.Furion.Application.Rbac.SignalRHub;
|
||||
using Yi.Furion.Web.Core.Handlers;
|
||||
|
||||
namespace Yi.Furion.Web.Core;
|
||||
@@ -25,6 +26,7 @@ public class Startup : AppStartup
|
||||
services.AddEventBus();
|
||||
|
||||
services.AddHttpContextAccessor();
|
||||
services.AddSignalR();
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
@@ -44,9 +46,9 @@ public class Startup : AppStartup
|
||||
app.UseAuthorization();
|
||||
|
||||
app.UseInject(string.Empty);
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapHub<OnlineUserHub>("/api/hub/main");
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import request from '@/utils/request'
|
||||
// 查询在线用户列表
|
||||
export function list(query) {
|
||||
return request({
|
||||
url: '/online/pageList',
|
||||
url: '/online',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
@@ -12,7 +12,7 @@ export function list(query) {
|
||||
// 强退用户
|
||||
export function forceLogout(tokenId) {
|
||||
return request({
|
||||
url: '/online/ForceOut/' + tokenId,
|
||||
url: '/online/' + tokenId,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ export default {
|
||||
})
|
||||
this.receiveMsg(connection);
|
||||
// 启动
|
||||
// this.start();
|
||||
this.start();
|
||||
},
|
||||
/**
|
||||
* 调用 this.signalR.start().then(async () => { await this.SR.invoke("method")})
|
||||
|
||||
@@ -81,7 +81,7 @@ const queryParams = ref({
|
||||
function getList() {
|
||||
loading.value = true;
|
||||
initData(queryParams.value).then(response => {
|
||||
onlineList.value = response.data.data;
|
||||
onlineList.value = response.data.items;
|
||||
total.value = response.data.total;
|
||||
loading.value = false;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user