You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

144 lines
5.0 KiB
C#

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
{
/// <summary>
/// 中间件
/// 记录用户方访问数据
/// </summary>
public class RecordAccessLogsMiddleware
{
/// <summary>
///
/// </summary>
private readonly RequestDelegate _next;
private readonly IUser _user;
private readonly ILogger<RecordAccessLogsMiddleware> _logger;
private readonly IWebHostEnvironment _environment;
private Stopwatch _stopwatch;
/// <summary>
///
/// </summary>
/// <param name="next"></param>
public RecordAccessLogsMiddleware(RequestDelegate next, IUser user, ILogger<RecordAccessLogsMiddleware> 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; }
}
}