using System.Diagnostics; using System.Security.Claims; using System.Text; using System.Web; using DS.Module.Core; using DS.Module.Core.Extensions; using DS.Module.Core.Log; using DS.Module.UserModule; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.Extensions.DependencyInjection; using NetTaste; using Newtonsoft.Json; using SqlSugar; using UAParser; using Parser = UAParser.Parser; namespace DS.Module.Middleware; /// /// 中间件 /// 记录用户方访问数据 /// public class OperationLogMiddleware { /// /// /// private readonly RequestDelegate _next; private Stopwatch _stopwatch; private readonly IUser user; private readonly IServiceProvider _serviceProvider; private readonly SqlSugarScope db; /// /// /// /// public OperationLogMiddleware(RequestDelegate next, IServiceProvider serviceProvider) { _next = next; _stopwatch = new Stopwatch(); _serviceProvider = serviceProvider; user = _serviceProvider.GetRequiredService(); db = (SqlSugarScope)_serviceProvider.GetRequiredService(); } public async Task InvokeAsync(HttpContext context) { if (AppSetting.app("Middleware", "RecordAccessLogs", "Enabled").ObjToBool()) { var api = context.Request.Path.ObjToString().TrimEnd('/').ToLower(); if (context.Request.Path.HasValue && ( context.Request.Path.Value.IndexOf("SignalR", StringComparison.InvariantCultureIgnoreCase) > -1 || context.Request.Path.Value.IndexOf("swagger", StringComparison.InvariantCultureIgnoreCase) > -1 || context.Request.Path.Value.IndexOf("HealthCheck", StringComparison.InvariantCultureIgnoreCase) > -1 ) ) { await _next(context); } var ignoreApis = AppSetting.app("Middleware", "RecordAccessLogs", "IgnoreApis"); // 过滤,只有接口 if (api.Contains("api") && !ignoreApis.Contains(api)) { _stopwatch.Restart(); HttpRequest request = context.Request; //判断是否请求成功(没有异常就是请求成功) var headers = request.Headers; var clientInfo = headers.ContainsKey("User-Agent") ? Parser.GetDefault().Parse(headers["User-Agent"]) : null; var isWriteLog = false; var log = new SysLogOperation() { // Name = context.User?.FindFirstValue(ClaimConst.CLAINM_NAME), Ip = GetClientIP(context), Location = GetRequestUrlAddress(request), Browser = clientInfo?.UA.Family + clientInfo?.UA.Major, Os = clientInfo?.OS.Family + clientInfo?.OS.Major, Url = request.Path, // ClassName = context.Controller.ToString(), // MethodName = actionDescriptor?.ActionName, ReqMethod = request.Method, OpTime = DateTime.Now, }; // 获取请求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); log.Param = Encoding.UTF8.GetString(buffer); request.Body.Position = 0; } else if (request.Method.ToLower().Equals("get") || request.Method.ToLower().Equals("delete")) { log.Param = HttpUtility.UrlDecode(request.QueryString.ObjToString(), Encoding.UTF8); } await _next(context); // // 获取Response.Body内容 // var originalBodyStream = context.Response.Body; // // using (var responseBody = new MemoryStream()) // { // context.Response.Body = responseBody; // log.Result = await GetResponse(context.Response); // // await responseBody.CopyToAsync(originalBodyStream); // } // 响应完成记录时间和存入日志 context.Response.OnCompleted(() => { _stopwatch.Stop(); if (context.Response.StatusCode == 200 && !context.Response.HasStarted) { log.Success = true; } else { log.Success = false; } log.ElapsedTime = _stopwatch.ElapsedMilliseconds; return Task.CompletedTask; }); } else { await _next(context); } } else { await _next(context); } } 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 async Task GetResponse(HttpResponse response) { response.Body.Seek(0, SeekOrigin.Begin); var text = await new StreamReader(response.Body).ReadToEndAsync(); response.Body.Seek(0, SeekOrigin.Begin); return text; } // // 摘要: // 获取完整请求地址 // // 参数: // request: public static string GetRequestUrlAddress(HttpRequest request) { return new StringBuilder().Append(request.Scheme).Append("://").Append(request.Host) .Append(request.PathBase) .Append(request.Path) .Append(request.QueryString) .ToString(); } }