| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 | using OASystem.Domain.AesEncryption;using OASystem.Domain.Attributes;using OASystem.Domain.Entities.Customer;using Org.BouncyCastle.Asn1.Pkcs;using System.Net;using UAParser;using static OASystem.API.OAMethodLib.JWTHelper;namespace OASystem.API.Middlewares{    /// <summary>    /// 指定API操作记录信息    /// </summary>    public class RecordAPIOperationMiddleware    {        private readonly RequestDelegate _next;        private readonly HttpClient _httpClient;        private readonly IConfiguration _config;        private readonly SqlSugarClient _sqlSugar;        /// <summary>        /// 初始化DeleteUserId        /// </summary>        /// <param name="next"></param>        /// <param name="config"></param>        /// <param name="httpClient"></param>        /// <param name="sqlSugar"></param>        public RecordAPIOperationMiddleware(RequestDelegate next, IConfiguration config, HttpClient httpClient, SqlSugarClient sqlSugar)        {            _next = next;            _httpClient = httpClient;            _config = config;            _sqlSugar = sqlSugar;        }        public async Task InvokeAsync(HttpContext context)        {            // 启用请求体流的缓冲,允许多次读取            context.Request.EnableBuffering();            // 读取请求体内容            var requestBodyText = await ReadRequestBody(context.Request);            // 检查控制器方法是否使用了自定义属性            var endpoint = context.GetEndpoint();            var apiLogAttribute = endpoint?.Metadata?.GetMetadata<ApiLogAttribute>();            if (apiLogAttribute != null)            {                var startTime = DateTime.UtcNow;                int portType = 1, userId = 0, id = 0, status = 0;                string updatePreData = string.Empty, updateBefData = string.Empty;                bool param5Bool = false, param6Bool = false;                try                {                    userId = await ReadToken(context);                    if (!string.IsNullOrEmpty(requestBodyText))                    {                        object param1 = string.Empty, param2 = string.Empty, param3 = string.Empty, param4 = string.Empty,                               param5 = string.Empty, param6 = string.Empty, param7 = string.Empty, param8 = string.Empty;                        var requestBodyJson = JsonConvert.DeserializeObject<Dictionary<string, object>>(requestBodyText);                        bool exists1 = requestBodyJson.TryGetValue("portType", out param1);                        bool exists2 = requestBodyJson.TryGetValue("userId", out param2);                        bool exists3 = requestBodyJson.TryGetValue("currUserId", out param3);                        bool exists4 = requestBodyJson.TryGetValue("createUserId", out param4);                        bool exists5 = requestBodyJson.TryGetValue("id", out param5);                        bool exists6 = requestBodyJson.TryGetValue("status", out param6);                        bool exists7 = requestBodyJson.TryGetValue("operationUserId", out param7);                        bool exists8 = requestBodyJson.TryGetValue("deleteUserId", out param8);                        if (exists1) int.TryParse(param1.ToString(), out portType);                        //用户Id处理                        if (userId < 1)                        {                            if (apiLogAttribute.OperationEnum == OperationEnum.Login)                            {                                var number = requestBodyJson?["number"].ToString();                                if (!string.IsNullOrEmpty(number))                                {                                    var info = await _sqlSugar.Queryable<Sys_Users>().Where(x => x.IsDel == 0 && x.Number.Equals(number)).FirstAsync();                                    userId = info?.Id ?? 0;                                }                            }                            else                            {                                if (exists2) int.TryParse(param2.ToString(), out userId);                                else if (exists3) int.TryParse(param3.ToString(), out userId);                                else if (exists4) int.TryParse(param4.ToString(), out userId);                                else if (exists7) int.TryParse(param7.ToString(), out userId);                                else if (exists8) int.TryParse(param8.ToString(), out userId);                            }                        }                        //编辑前数据查询;                        if (exists5) param5Bool = int.TryParse(param5.ToString(), out id);                        if (exists6) param6Bool = int.TryParse(param6.ToString(), out status);                        if (param6Bool)                        {                            //  2 修改                             if (status == 1) apiLogAttribute.OperationEnum = OperationEnum.Add;                            else if (status == 2)                            {                                apiLogAttribute.OperationEnum = OperationEnum.Edit;                                updatePreData = await TableInfoToJson(apiLogAttribute.TableName, id);                            }                        }                        else if (param5Bool)                        {                            if (apiLogAttribute.OperationEnum != OperationEnum.Del)                            {                                //  id > 0 修改                                 if (id < 1) apiLogAttribute.OperationEnum = OperationEnum.Add;                                else if (id > 0)                                {                                    apiLogAttribute.OperationEnum = OperationEnum.Edit;                                    updatePreData = await TableInfoToJson(apiLogAttribute.TableName, id);                                }                            }                        }                    }                }                catch (JsonException) { }                // 保存原始响应体流                var originalResponseBody = context.Response.Body;                // 创建一个新的内存流来捕获响应体                using var responseMemoryStream = new MemoryStream();                context.Response.Body = responseMemoryStream;                // 调用下一个中间件                await _next(context);                // 重置响应体流的位置                responseMemoryStream.Position = 0;                // 读取响应体内容                var responseBodyText = await ReadResponseBody(responseMemoryStream);                // 将响应体内容写回原始响应体流                await responseMemoryStream.CopyToAsync(originalResponseBody);                //修改后数据查询                if (param6Bool)                {                    //  2 修改                     if (status == 2) updateBefData = await TableInfoToJson(apiLogAttribute.TableName, id);                }                else if (param5Bool)                {                    if (apiLogAttribute.OperationEnum != OperationEnum.Del)                    {                        //  id > 0 修改                         if (id > 0) updateBefData = await TableInfoToJson(apiLogAttribute.TableName, id);                    }                }                string remoteIp = string.Empty,                       location = string.Empty;                // 检查请求头中的X-Forwarded-For,以获取真实的客户端IP地址                if (context.Request.Headers.ContainsKey("X-Forwarded-For"))                {                    remoteIp = context.Request.Headers["X-Forwarded-For"].ToString().Split(',', StringSplitOptions.RemoveEmptyEntries)[0];                    //_logger.LogInformation($"IP:{remoteIp}");                }                else                {                    remoteIp = context.Connection.RemoteIpAddress?.ToString();                }                (remoteIp, location) = await GetIpInfo(remoteIp);                //remoteIp = await GetExternalIp();                //location = await GetIpLocation(remoteIp);                string deviceType = string.Empty, browser = string.Empty, os = string.Empty;                var userAgent = context.Request.Headers["User-Agent"].FirstOrDefault();                if (!string.IsNullOrEmpty(userAgent))                {                    // 解析User-Agent头                    var parser = Parser.GetDefault();                    var client = parser.Parse(userAgent);                    // 提取浏览器信息                    browser = client.UA.Family; // 浏览器名称                    var browserVersion = client.UA.Major + "." + client.UA.Minor + "." + client.UA.Patch; // 浏览器版本                    browser += $"({browserVersion})";                    // 提取操作系统信息                    os = client.OS.Family; // 操作系统名称                    var osVersion = string.Empty; // 操作系统版本                    if (!string.IsNullOrEmpty(client.OS.Major)) osVersion += client.OS.Major;                    if (!string.IsNullOrEmpty(client.OS.Minor)) osVersion += "." + client.OS.Minor;                    if (!string.IsNullOrEmpty(client.OS.Patch)) osVersion += "." + client.OS.Patch;                    if (!string.IsNullOrEmpty(osVersion)) os += $"({osVersion})";                    // 提取设备信息                    deviceType = client.Device.Family; // 设备类型,如 'mobile', 'tablet', 'desktop' 等                }                // 记录请求结束时间                var endTime = DateTime.UtcNow;                // 计算耗时                var duration = (long)(endTime - startTime).TotalMilliseconds;                var logInfo = new Crm_TableOperationRecord()                {                    TableName = apiLogAttribute.TableName,                    PortType = portType,                    OperationItem = apiLogAttribute.OperationEnum,                    DataId = id,                    RequestUrl = context.Request.Path,                    RemoteIp = remoteIp,                    Location = location,                    RequestParam = !string.IsNullOrEmpty(requestBodyText) ? JsonConvert.SerializeObject(requestBodyText) : null,                    ReturnResult = !string.IsNullOrEmpty(responseBodyText) ? JsonConvert.SerializeObject(responseBodyText) : null,                    Elapsed = duration,                    Status = context.Response.StatusCode.ToString(),                    CreateUserId = userId,                    UpdatePreData = updatePreData,                    UpdateBefData = updateBefData,                    Browser = browser,                    Os = os,                    DeviceType = deviceType,                };                // 存储到数据库                await _sqlSugar.Insertable(logInfo).ExecuteCommandAsync();            }            else            {                await _next(context);            }        }        private async Task<string> TableInfoToJson(string tableName, int id)        {            if (_sqlSugar.DbMaintenance.IsAnyTable(tableName))            {                string jsonLabel = string.Empty;                if (tableName.Equals("Crm_NewClientData"))                {                    var info = await _sqlSugar.Queryable<Crm_NewClientData>().FirstAsync(x => x.Id == id);                    if (info != null)                    {                        EncryptionProcessor.DecryptProperties(info);                        if (info != null) jsonLabel = JsonConvert.SerializeObject(info);                    }                }                else                {                    var sql = string.Format(" Select * From {0} Where Id={1}", tableName, id);                    var info = await _sqlSugar.SqlQueryable<dynamic>(sql).FirstAsync();                    if (info != null) jsonLabel = JsonConvert.SerializeObject(info);                }                return jsonLabel;            }            return string.Empty;        }        private async Task<string> ReadRequestBody(HttpRequest request)        {            request.EnableBuffering();            using var reader = new StreamReader(                request.Body,                Encoding.UTF8,                detectEncodingFromByteOrderMarks: false,                bufferSize: 8192,                leaveOpen: true            );            var body = await reader.ReadToEndAsync();            request.Body.Position = 0;            return body;        }        private async Task<string> ReadResponseBody(Stream stream)        {            using var reader = new StreamReader(                stream,                Encoding.UTF8,                detectEncodingFromByteOrderMarks: false,                bufferSize: 8192,                leaveOpen: true            );            var body = await reader.ReadToEndAsync();            stream.Position = 0;            return body;        }        private async Task<int> ReadToken(HttpContext context)        {            var authHeader = context.Request.Headers["Authorization"].FirstOrDefault();            // 检查Authorization头是否存在且以"Bearer "开头            if (!string.IsNullOrEmpty(authHeader) && authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))            {                var authInfo = JwtHelper.SerializeJwt(authHeader);                if (authInfo != null) return authInfo.UserId;            }            return 0;        }        /// <summary>        /// 获取IP信息        /// </summary>        /// <param name="ip">ipv4 or ipv6</param>        /// <returns></returns>        private async Task<(string ip, string local)> GetIpInfo(string ip)        {            string local = string.Empty;            //if (IPAddress.TryParse(ip,out _))            //{            //    var response = await _httpClient.GetAsync($"https://api.vore.top/api/IPdata?ip={ip}");            //    response.EnsureSuccessStatusCode();            //    var json = await response.Content.ReadAsStringAsync();            //    var ipInfo = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(json);            //    if (ipInfo.code == 200)            //    {            //        ip = ipInfo.ipinfo.text;            //        local = $"{ipInfo.adcode.o}";            //    }            //}            return (ip, local);        }        private async Task<string> GetExternalIp()        {            var response = await _httpClient.GetAsync("https://ifconfig.me");            response.EnsureSuccessStatusCode();            return await response.Content.ReadAsStringAsync();        }        private async Task<string> GetIpLocation(string ip)        {            var response = await _httpClient.GetAsync($"https://ipinfo.io/{ip}/json?&language=zh-CN");            response.EnsureSuccessStatusCode();            var json = await response.Content.ReadAsStringAsync();            var ipInfo = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(json);            return $"{ipInfo.country}, {ipInfo.city}";        }    }}
 |