|
-
- //
-
-
-
-
-
-
-
-
- using Masuit.Tools;
- using Microsoft.Extensions.Logging;
- using NewLife.Serialization;
- using SqlSugar;
- using System.Globalization;
- using UAParser;
-
- namespace SafeCampus.Web.Core;
-
- /// <summary>
- /// 数据库写入器
- /// </summary>
- public class DatabaseLoggingWriter : IDatabaseLoggingWriter
- {
- private readonly ISearcher _searcher;
- private readonly SqlSugarScope _db;
- private readonly ILogger<DatabaseLoggingWriter> _logger;
-
- public DatabaseLoggingWriter(ILogger<DatabaseLoggingWriter> 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<LoggingMonitorJson>();
- //日志时间赋值
- 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);
- }
- }
- }
- }
-
- /// <summary>
- /// 创建访问日志
- /// </summary>
- /// <param name="operation">访问类型</param>
- /// <param name="loggingMonitor">loggingMonitor</param>
- /// <param name="clientInfo">客户端信息</param>
- 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<SafeCampusResult<SysUser>>();//格式化成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();//入库
- }
-
- /// <summary>
- /// 创建操作日志
- /// </summary>
- /// <param name="operation">操作名称</param>
- /// <param name="path">请求地址</param>
- /// <param name="loggingMonitor">loggingMonitor</param>
- /// <param name="clientInfo">客户端信息</param>
- /// <returns></returns>
- 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();//入库
- }
-
- /// <summary>
- /// 解析IP地址
- /// </summary>
- /// <param name="ip"></param>
- /// <returns></returns>
- 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;
- }
- }
|