// using Masuit.Tools; using Microsoft.Extensions.Logging; using NewLife.Serialization; using SqlSugar; using System.Globalization; using UAParser; namespace SafeCampus.Web.Core; /// /// 数据库写入器 /// public class DatabaseLoggingWriter : IDatabaseLoggingWriter { private readonly ISearcher _searcher; private readonly SqlSugarScope _db; private readonly ILogger _logger; public DatabaseLoggingWriter(ILogger logger, ISearcher searcher) { _db = DbContext.DB; _logger = logger; _searcher = searcher; } public async Task WriteAsync(LogMessage logMsg, bool flush) { //获取请求json字符串 var jsonString = logMsg.Context.Get("loggingMonitor").ToString(); //转成实体 var loggingMonitor = jsonString.ToJsonEntity(); //日志时间赋值 loggingMonitor.LogDateTime = logMsg.LogDateTime; // loggingMonitor.ReturnInformation.Value //验证失败和没有DisplayTitle之类的不记录日志 if (loggingMonitor.Validation == null && loggingMonitor.DisplayTitle != null) { //获取操作名称 var operation = loggingMonitor.DisplayTitle; var client = (ClientInfo)logMsg.Context.Get(LoggingConst.CLIENT);//获取客户端信息 var path = logMsg.Context.Get(LoggingConst.PATH).ToString();//获取操作名称 var method = logMsg.Context.Get(LoggingConst.METHOD).ToString();//获取方法 //表示访问日志 if (operation == EventSubscriberConst.LOGIN_B || operation == EventSubscriberConst.LOGIN_OUT_B) { //如果没有异常信息 if (loggingMonitor.Exception == null) { await CreateVisitLog(operation, loggingMonitor, client);//添加到访问日志 } else { //添加到异常日志 await CreateOperationLog(operation, path, loggingMonitor, client); } } else { //只有定义了Title的POST方法才记录日志 if (!operation.Contains("/") && method == "POST") { //添加到操作日志 await CreateOperationLog(operation, path, loggingMonitor, client); } } } } /// /// 创建访问日志 /// /// 访问类型 /// loggingMonitor /// 客户端信息 private async Task CreateVisitLog(string operation, LoggingMonitorJson loggingMonitor, ClientInfo clientInfo) { string name;//用户姓名 string opAccount;//用户账号 if (operation == EventSubscriberConst.LOGIN_B) { //如果是登录,用户信息就从返回值里拿 var result = loggingMonitor.ReturnInformation.Value.ToJson();//返回值转json var userInfo = result.ToJsonEntity>();//格式化成user表 name = userInfo.Data.Name;//赋值姓名 opAccount = userInfo.Data.Account;//赋值账号 } else { //如果是登录出,用户信息就从AuthorizationClaims里拿 name = loggingMonitor.AuthorizationClaims.Where(it => it.Type == ClaimConst.NAME).Select(it => it.Value).FirstOrDefault(); opAccount = loggingMonitor.AuthorizationClaims.Where(it => it.Type == ClaimConst.ACCOUNT).Select(it => it.Value).FirstOrDefault(); } //日志表实体 var devLogVisit = new SysLogVisit { Name = operation, Category = operation == EventSubscriberConst.LOGIN_B ? CateGoryConst.LOG_LOGIN : CateGoryConst.LOG_LOGOUT, ExeStatus = SysLogConst.SUCCESS, OpAddress = GetLoginAddress(loggingMonitor.RemoteIPv4), OpIp = loggingMonitor.RemoteIPv4, OpBrowser = clientInfo.UA.Family + clientInfo.UA.Major, OpOs = clientInfo.OS.Family + clientInfo.OS.Major, OpTime = loggingMonitor.LogDateTime, OpUser = name, OpAccount = opAccount }; await _db.CopyNew().InsertableWithAttr(devLogVisit).IgnoreColumns(true).SplitTable().ExecuteCommandAsync();//入库 } /// /// 创建操作日志 /// /// 操作名称 /// 请求地址 /// loggingMonitor /// 客户端信息 /// private async Task CreateOperationLog(string operation, string path, LoggingMonitorJson loggingMonitor, ClientInfo clientInfo) { //用户名称 var name = loggingMonitor.AuthorizationClaims?.Where(it => it.Type == ClaimConst.NAME).Select(it => it.Value).FirstOrDefault(); //账号 var opAccount = loggingMonitor.AuthorizationClaims?.Where(it => it.Type == ClaimConst.ACCOUNT).Select(it => it.Value).FirstOrDefault(); //获取参数json字符串, var paramJson = loggingMonitor.Parameters == null || loggingMonitor.Parameters.Count == 0 ? null : loggingMonitor.Parameters[0].Value.ToJsonString(); //获取结果json字符串 var resultJson = string.Empty; if (loggingMonitor.ReturnInformation != null)//如果有返回值 { if (loggingMonitor.ReturnInformation.Value != null)//如果返回值不为空 { var time = loggingMonitor.ReturnInformation.Value.Time != null ? DateTime.Parse(loggingMonitor.ReturnInformation.Value.Time) : DateTime.Now;//转成时间 loggingMonitor.ReturnInformation.Value.Time = time.ToString(CultureInfo.CurrentCulture);//转成字符串 resultJson = loggingMonitor.ReturnInformation.Value.ToJsonString(); } } //操作日志表实体 var devLogOperate = new SysLogOperate { Name = operation, Category = CateGoryConst.LOG_OPERATE, ExeStatus = SysLogConst.SUCCESS, OpAddress = GetLoginAddress(loggingMonitor.RemoteIPv4), OpIp = loggingMonitor.RemoteIPv4, OpBrowser = clientInfo.UA.Family + clientInfo.UA.Major, OpOs = clientInfo.OS.Family + clientInfo.OS.Major, OpTime = loggingMonitor.LogDateTime, OpUser = name, OpAccount = opAccount, ReqMethod = loggingMonitor.HttpMethod, ReqUrl = path, ResultJson = resultJson, ClassName = loggingMonitor.DisplayName, MethodName = loggingMonitor.ActionName, ParamJson = paramJson }; //如果异常不为空 if (loggingMonitor.Exception != null) { devLogOperate.Category = CateGoryConst.LOG_EXCEPTION;//操作类型为异常 devLogOperate.ExeStatus = SysLogConst.FAIL;//操作状态为失败 devLogOperate.ExeMessage = loggingMonitor.Exception.Type + ":" + loggingMonitor.Exception.Message + "\n" + loggingMonitor.Exception.StackTrace; } await _db.CopyNew().InsertableWithAttr(devLogOperate).IgnoreColumns(true).SplitTable().ExecuteCommandAsync();//入库 } /// /// 解析IP地址 /// /// /// private string GetLoginAddress(string ip) { var loginAddress = "未知"; try { var ipInfo = _searcher.Search(ip);//解析ip loginAddress = ipInfo?.Replace("0|", "");//去掉前面的0| } catch (global::System.Exception ex) { _logger.LogError("IP解析错误" + ex, ex); } return loginAddress; } }