using EntrustSettle.Common; using EntrustSettle.Common.HttpContextUser; using EntrustSettle.Common.LogHelper; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using System; using System.Diagnostics; using System.IO; using System.Text; using System.Threading.Tasks; using System.Web; namespace EntrustSettle.Extensions.Middlewares { /// /// 中间件 /// 记录用户方访问数据 /// public class RecordAccessLogsMiddleware { /// /// /// private readonly RequestDelegate _next; private readonly IUser _user; private readonly ILogger _logger; private readonly IWebHostEnvironment _environment; private Stopwatch _stopwatch; /// /// /// /// public RecordAccessLogsMiddleware(RequestDelegate next, IUser user, ILogger logger, IWebHostEnvironment environment) { _next = next; _user = user; _logger = logger; _environment = environment; _stopwatch = new Stopwatch(); } public async Task InvokeAsync(HttpContext context) { if (!AppSettings.app("Middleware", "RecordAccessLogs", "Enabled").ObjToBool()) { await _next(context); return; } // 判断如果请求中含有文件上传,不记录日志 if (context.Request.HasFormContentType && context.Request.Form.Files.Count > 0) { await _next(context); return; } // 过滤,只有接口才记录 var api = context.Request.Path.ObjToString().TrimEnd('/'); var ignoreApis = AppSettings.app("Middleware", "RecordAccessLogs", "IgnoreApis"); if (!api.Contains("api",StringComparison.OrdinalIgnoreCase) || ignoreApis.Contains(api,StringComparison.OrdinalIgnoreCase)) { await _next(context); return; } _stopwatch.Restart(); var userAccessModel = new UserAccessModel(); HttpRequest request = context.Request; userAccessModel.API = api; userAccessModel.User = _user.Name; userAccessModel.IP = GetClientIP(context); userAccessModel.BeginTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); userAccessModel.RequestMethod = request.Method; userAccessModel.Agent = request.Headers["User-Agent"].ObjToString(); // 获取请求body内容 if (request.Method.ToLower().Equals("post") || request.Method.ToLower().Equals("put")) { // 启用倒带功能,就可以让 Request.Body 可以再次读取 request.EnableBuffering(); Stream stream = request.Body; byte[] buffer = new byte[request.ContentLength.Value]; stream.Read(buffer, 0, buffer.Length); userAccessModel.RequestData = Encoding.UTF8.GetString(buffer); request.Body.Position = 0; } else if (request.Method.ToLower().Equals("get") || request.Method.ToLower().Equals("delete")) { userAccessModel.RequestData = HttpUtility.UrlDecode(request.QueryString.ObjToString(), Encoding.UTF8); } await _next(context); // 响应完成记录时间和存入日志 context.Response.OnCompleted(() => { _stopwatch.Stop(); userAccessModel.OPTime = _stopwatch.ElapsedMilliseconds + "ms"; // 自定义log输出 var requestInfo = JsonConvert.SerializeObject(userAccessModel); Parallel.For(0, 1, e => { //LogLock.OutSql2Log("RecordAccessLogs", new string[] { requestInfo + "," }, false); LogLock.OutLogAOP("RecordAccessLogs", context.TraceIdentifier, new string[] { userAccessModel.GetType().ToString(), requestInfo }, false); }); return Task.CompletedTask; }); } public static string GetClientIP(HttpContext context) { var ip = context.Request.Headers["X-Forwarded-For"].ObjToString(); if (string.IsNullOrEmpty(ip)) { ip = context.Connection.RemoteIpAddress.ObjToString(); } return ip; } } public class UserAccessModel { public string User { get; set; } public string IP { get; set; } public string API { get; set; } public string BeginTime { get; set; } public string OPTime { get; set; } public string RequestMethod { get; set; } public string RequestData { get; set; } public string Agent { get; set; } } }