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.

193 lines
6.6 KiB
C#

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;
/// <summary>
/// 中间件
/// 记录用户方访问数据
/// </summary>
public class OperationLogMiddleware
{
/// <summary>
///
/// </summary>
private readonly RequestDelegate _next;
private Stopwatch _stopwatch;
private readonly IUser user;
private readonly IServiceProvider _serviceProvider;
private readonly SqlSugarScope db;
/// <summary>
///
/// </summary>
/// <param name="next"></param>
public OperationLogMiddleware(RequestDelegate next, IServiceProvider serviceProvider)
{
_next = next;
_stopwatch = new Stopwatch();
_serviceProvider = serviceProvider;
user = _serviceProvider.GetRequiredService<IUser>();
db = (SqlSugarScope)_serviceProvider.GetRequiredService<ISqlSugarClient>();
}
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;
}
/// <summary>
/// 获取响应内容
/// </summary>
/// <param name="response"></param>
/// <returns></returns>
public async Task<string> 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();
}
}