diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Extensions/HttpContextExtensions.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Extensions/HttpContextExtensions.cs new file mode 100644 index 00000000..759555ed --- /dev/null +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.AspNetCore/Extensions/HttpContextExtensions.cs @@ -0,0 +1,48 @@ +using Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Yi.Framework.AspNetCore.Extensions +{ + public static class HttpContextExtensions + { + /// + /// 获取客户端IP + /// + /// + /// + public static string GetClientIp(this HttpContext context) + { + if (context == null) return ""; + var result = context.Request.Headers["X-Forwarded-For"].FirstOrDefault(); + if (string.IsNullOrEmpty(result)) + { + result = context.Connection.RemoteIpAddress?.ToString(); + } + if (string.IsNullOrEmpty(result) || result.Contains("::1")) + result = "127.0.0.1"; + + result = result.Replace("::ffff:", "127.0.0.1"); + + //Ip规则效验 + var regResult = Regex.IsMatch(result, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$"); + + result = regResult ? result : "127.0.0.1"; + return result; + } + + /// + /// 获取浏览器标识 + /// + /// + /// + public static string GetUserAgent(this HttpContext context) + { + return context.Request.Headers["User-Agent"]; + } + } +} diff --git a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Application.Contracts/ApplicationContractsSwaggerDoc.xml b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Application.Contracts/ApplicationContractsSwaggerDoc.xml index d5bee59e..a211a924 100644 --- a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Application.Contracts/ApplicationContractsSwaggerDoc.xml +++ b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Application.Contracts/ApplicationContractsSwaggerDoc.xml @@ -74,6 +74,26 @@ User服务抽象 + + + 登录Ip + + + + + 浏览器 + + + + + 操作系统 + + + + + 登录信息 + + Config输入创建对象 diff --git a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Application.Contracts/Logs/Dtos/LoginLog/LoginLogGetListInputVo.cs b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Application.Contracts/Logs/Dtos/LoginLog/LoginLogGetListInputVo.cs new file mode 100644 index 00000000..c35b995a --- /dev/null +++ b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Application.Contracts/Logs/Dtos/LoginLog/LoginLogGetListInputVo.cs @@ -0,0 +1,17 @@ +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Yi.Framework.Ddd.Dtos; + +namespace Yi.RBAC.Application.Contracts.Logs.Dtos.LoginLog +{ + public class LoginLogGetListInputVo: PagedAllResultRequestDto + { + public string? LoginUser { get; set; } + + public string? LoginIp { get; set; } + } +} diff --git a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Application.Contracts/Logs/Dtos/LoginLog/LoginLogGetListOutputDto.cs b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Application.Contracts/Logs/Dtos/LoginLog/LoginLogGetListOutputDto.cs new file mode 100644 index 00000000..3ca4a77d --- /dev/null +++ b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Application.Contracts/Logs/Dtos/LoginLog/LoginLogGetListOutputDto.cs @@ -0,0 +1,38 @@ +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Yi.Framework.Ddd.Dtos; + +namespace Yi.RBAC.Application.Contracts.Logs.Dtos.LoginLog +{ + public class LoginLogGetListOutputDto:EntityDto + { + public DateTime CreationTime { get; } + + + public string? LoginUser { get; set; } + + public string? LoginLocation { get; set; } + /// + /// 登录Ip + /// + public string? LoginIp { get; set; } + /// + /// 浏览器 + /// + public string? Browser { get; set; } + /// + /// 操作系统 + /// + public string? Os { get; set; } + /// + /// 登录信息 + /// + public string? LogMsg { get; set; } + + public long? CreatorId { get; set; } + } +} diff --git a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Application/Logs/LoginLogService.cs b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Application/Logs/LoginLogService.cs new file mode 100644 index 00000000..183c206e --- /dev/null +++ b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Application/Logs/LoginLogService.cs @@ -0,0 +1,32 @@ +using NET.AutoWebApi.Setting; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Yi.Framework.Ddd.Dtos; +using Yi.Framework.Ddd.Services; +using Yi.RBAC.Application.Contracts.Logs.Dtos.LoginLog; +using Yi.RBAC.Application.Contracts.Setting.Dtos; +using Yi.RBAC.Domain.Logs.Entities; + +namespace Yi.RBAC.Application.Logs +{ + [AppService] + public class LoginLogService : CrudAppService, IAutoApiService + { + public override async Task> GetListAsync(LoginLogGetListInputVo input) + { + var entity = await MapToEntityAsync(input); + + RefAsync total = 0; + + var entities = await _DbQueryable.WhereIF(!string.IsNullOrEmpty(input.LoginIp), x => x.LoginIp.Contains(input.LoginIp!)) + .WhereIF(!string.IsNullOrEmpty(input.LoginUser), x => x.LoginUser!.Contains(input.LoginUser!)) + .WhereIF(input.StartTime is not null && input.EndTime is not null, x => x.CreationTime >= input.StartTime && x.CreationTime <= input.EndTime) + .ToPageListAsync(input.PageNum, input.PageSize, total); + return new PagedResultDto(total, await MapToGetListOutputDtosAsync(entities)); + } + } +} diff --git a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain.Shared/Identity/Etos/LoginEventArgs.cs b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain.Shared/Identity/Etos/LoginEventArgs.cs index 925b5eea..102d43d6 100644 --- a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain.Shared/Identity/Etos/LoginEventArgs.cs +++ b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain.Shared/Identity/Etos/LoginEventArgs.cs @@ -11,5 +11,6 @@ namespace Yi.RBAC.Domain.Shared.Identity.Etos public long UserId { get; set; } public string UserName { get; set; } + public string LogMsg { get; set; } } } diff --git a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/DomainSwaggerDoc.xml b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/DomainSwaggerDoc.xml index eba4aa75..92e534db 100644 --- a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/DomainSwaggerDoc.xml +++ b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/DomainSwaggerDoc.xml @@ -711,6 +711,36 @@ + + + 登录用户 + + + + + 登录地点 + + + + + 登录Ip + + + + + 浏览器 + + + + + 操作系统 + + + + + 登录信息 + + 配置表 diff --git a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/Identity/Event/LoginEventHandler .cs b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/Identity/Event/LoginEventHandler .cs deleted file mode 100644 index 2cd87ee3..00000000 --- a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/Identity/Event/LoginEventHandler .cs +++ /dev/null @@ -1,19 +0,0 @@ -using Cike.EventBus.EventHandlerAbstracts; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Yi.RBAC.Domain.Shared.Identity.Etos; - -namespace Yi.RBAC.Domain.Identity.Event -{ - public class LoginEventHandler : IDistributedEventHandler - { - public Task HandlerAsync(LoginEventArgs eventData) - { - Console.WriteLine(eventData.UserName+"登录系统"); - return Task.CompletedTask; - } - } -} diff --git a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/Logs/Entities/LoginLogEntity.cs b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/Logs/Entities/LoginLogEntity.cs new file mode 100644 index 00000000..4aa2fea1 --- /dev/null +++ b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/Logs/Entities/LoginLogEntity.cs @@ -0,0 +1,52 @@ +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Yi.Framework.Data.Auditing; +using Yi.Framework.Ddd.Entities; + +namespace Yi.RBAC.Domain.Logs.Entities +{ + [SugarTable("LoginLog")] + public class LoginLogEntity : IEntity, ICreationAuditedObject + { + [SugarColumn(ColumnName = "Id", IsPrimaryKey = true)] + public long Id { get; set; } + public DateTime CreationTime { get; } + + /// + /// 登录用户 + /// + [SugarColumn(ColumnName = "LoginUser")] + public string? LoginUser { get; set; } + /// + /// 登录地点 + /// + [SugarColumn(ColumnName = "LoginLocation")] + public string? LoginLocation { get; set; } + /// + /// 登录Ip + /// + [SugarColumn(ColumnName = "LoginIp")] + public string? LoginIp { get; set; } + /// + /// 浏览器 + /// + [SugarColumn(ColumnName = "Browser")] + public string? Browser { get; set; } + /// + /// 操作系统 + /// + [SugarColumn(ColumnName = "Os")] + public string? Os { get; set; } + /// + /// 登录信息 + /// + [SugarColumn(ColumnName = "LogMsg")] + public string? LogMsg { get; set; } + + public long? CreatorId { get; set; } + } +} diff --git a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/Logs/Event/LoginEventHandler .cs b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/Logs/Event/LoginEventHandler .cs new file mode 100644 index 00000000..7ff2d211 --- /dev/null +++ b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/Logs/Event/LoginEventHandler .cs @@ -0,0 +1,36 @@ +using Cike.EventBus.EventHandlerAbstracts; +using Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using Yi.Framework.Ddd.Repositories; +using Yi.RBAC.Domain.Logs.Entities; +using Yi.RBAC.Domain.Shared.Identity.Etos; + +namespace Yi.RBAC.Domain.Logs.Event +{ + public class LoginEventHandler : IDistributedEventHandler + { + private readonly IRepository _loginLogRepository; + private readonly HttpContext _httpContext; + public LoginEventHandler(IRepository loginLogRepository, IHttpContextAccessor httpContextAccessor) + { + _loginLogRepository = loginLogRepository; + _httpContext = httpContextAccessor.HttpContext; + } + public Task HandlerAsync(LoginEventArgs eventData) + { + var loginLogEntity = new LoginLogEntity(); + loginLogEntity.Id = SnowflakeHelper.NextId; + loginLogEntity.LogMsg = eventData.LogMsg; + loginLogEntity.LoginUser = eventData.UserName; + + _loginLogRepository.InsertAsync(loginLogEntity); + Console.WriteLine(eventData.UserName + "登录系统"); + return Task.CompletedTask; + } + } +} diff --git a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Web/yi-sqlsugar-dev.db b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Web/yi-sqlsugar-dev.db index 78a5f2e4..54b2b159 100644 Binary files a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Web/yi-sqlsugar-dev.db and b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Web/yi-sqlsugar-dev.db differ diff --git a/Yi.RuoYi.Vue3/src/api/monitor/logininfor.js b/Yi.RuoYi.Vue3/src/api/monitor/logininfor.js index a3881ea4..104ec1bd 100644 --- a/Yi.RuoYi.Vue3/src/api/monitor/logininfor.js +++ b/Yi.RuoYi.Vue3/src/api/monitor/logininfor.js @@ -3,7 +3,7 @@ import request from '@/utils/request' // 查询登录日志列表 export function list(query) { return request({ - url: '/loginLog/pageList', + url: '/login-log', method: 'get', params: query }) @@ -12,9 +12,8 @@ export function list(query) { // 删除登录日志 export function delLogininfor(infoId) { return request({ - url: '/loginLog/delList', - method: 'delete', - data:"string"==typeof(infoId)?[infoId]:infoId + url: `/login-log/${infoId}`, + method: 'delete' }) } diff --git a/Yi.RuoYi.Vue3/src/views/monitor/logininfor/index.vue b/Yi.RuoYi.Vue3/src/views/monitor/logininfor/index.vue index ea272b36..4e2bc6af 100644 --- a/Yi.RuoYi.Vue3/src/views/monitor/logininfor/index.vue +++ b/Yi.RuoYi.Vue3/src/views/monitor/logininfor/index.vue @@ -155,7 +155,7 @@ const queryParams = ref({ function getList() { loading.value = true; list(proxy.addDateRange(queryParams.value, dateRange.value)).then(response => { - logininforList.value = response.data.data; + logininforList.value = response.data.items; total.value = response.data.total; loading.value = false; });