|
using Microsoft.AspNetCore.Http;
|
using Microsoft.Extensions.Logging;
|
using Newtonsoft.Json;
|
using System;
|
using System.Collections.Generic;
|
using System.Diagnostics;
|
using System.IdentityModel.Tokens.Jwt;
|
using System.IO;
|
using System.Linq;
|
using System.Security.Claims;
|
using System.Text;
|
using System.Threading.Tasks;
|
using System.Web;
|
using CoreCms.Net.Configuration;
|
using CoreCms.Net.Filter;
|
using CoreCms.Net.IServices;
|
using CoreCms.Net.Loging;
|
using CoreCms.Net.Model.Entities;
|
using CoreCms.Net.Model.ViewModels.Basics;
|
using CoreCms.Net.Utility.Extensions;
|
using Microsoft.AspNetCore.Authentication;
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
|
namespace CoreCms.Net.Middlewares
|
{
|
/// <summary>
|
/// 中间件
|
/// 记录用户方访问数据
|
/// </summary>
|
public class RecordAccessLogsMildd
|
{
|
private readonly RequestDelegate _next;
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
private readonly ISysUserOperationLogServices _sysUserOperationLogServices;
|
|
private readonly Stopwatch _stopwatch;
|
|
private readonly string _dataSources;
|
|
|
/// <summary>
|
/// 构造
|
/// </summary>
|
public RecordAccessLogsMildd(RequestDelegate next, IHttpContextAccessor httpContextAccessor, ISysUserOperationLogServices sysUserOperationLogServices, string dataSources)
|
{
|
_next = next;
|
_httpContextAccessor = httpContextAccessor;
|
_dataSources = dataSources;
|
_sysUserOperationLogServices = sysUserOperationLogServices;
|
_stopwatch = new Stopwatch();
|
}
|
|
public async Task InvokeAsync(HttpContext context)
|
{
|
//用户访问记录-是否开启
|
var middlewareRecordAccessLogsEnabled = AppSettingsConstVars.MiddlewareRecordAccessLogsEnabled;
|
//是否开启记录到文件模式
|
var middlewareRecordAccessLogsEnabledFileMode = AppSettingsConstVars.MiddlewareRecordAccessLogsEnabledFileMode;
|
//是否开启记录到数据库模式
|
var middlewareRecordAccessLogsEnabledDbMode = AppSettingsConstVars.MiddlewareRecordAccessLogsEnabledDbMode;
|
|
if (middlewareRecordAccessLogsEnabled && (middlewareRecordAccessLogsEnabledFileMode || middlewareRecordAccessLogsEnabledDbMode))
|
{
|
var request = context.Request;
|
var api = request.Path.ObjectToString().TrimEnd('/').ToLower();
|
var ignoreApis = AppSettingsConstVars.MiddlewareRecordAccessLogsIgnoreApis;
|
|
// 过滤,只有接口
|
if (api.Contains("api") && !ignoreApis.ToLower().Contains(api))
|
{
|
_stopwatch.Restart();
|
var uLog = new SysUserOperationLog();
|
|
if (_httpContextAccessor.HttpContext != null)
|
{
|
var authenticate = await _httpContextAccessor.HttpContext.AuthenticateAsync(JwtBearerDefaults.AuthenticationScheme);
|
if (authenticate.Succeeded && authenticate.Principal != null)
|
{
|
//账号
|
uLog.userName = authenticate.Principal.Identities.First().FindFirst(ClaimTypes.Name)?.Value;
|
//昵称
|
uLog.userNickName = authenticate.Principal.Identities.First().FindFirst(ClaimTypes.GivenName)?.Value;
|
//用户序列
|
uLog.userId = authenticate.Principal.Identities.First().FindFirst(JwtRegisteredClaimNames.Jti)!.Value.ObjectToInt(0);
|
}
|
|
var adminLog = AdminsControllerPermission.GetCacheCoreCmsActionPermission(_dataSources);
|
|
var curLog = adminLog.FirstOrDefault(p => p.path.ToLower() == _httpContextAccessor.HttpContext.Request.Path.Value.ToLower());
|
if (curLog != null)
|
{
|
uLog.actionName = curLog.actionName;
|
uLog.actionDescription = curLog.description;
|
uLog.controllerName = curLog.controllerName;
|
uLog.controllerDescription = curLog.controllerDescription;
|
}
|
uLog.apiPath = _httpContextAccessor.HttpContext.Request.Path.Value;
|
uLog.statusCode = _httpContextAccessor.HttpContext.Response.StatusCode;
|
}
|
else
|
{
|
uLog.apiPath = api;
|
}
|
|
uLog.ip = IPLogMildd.GetClientIp(context);
|
uLog.beginTime = DateTime.Now;
|
uLog.requestMethod = request.Method;
|
uLog.agent = request.Headers["User-Agent"].ObjectToString();
|
uLog.dataSources = _dataSources;
|
|
switch (request.Method.ToLower())
|
{
|
// 获取请求body内容
|
case "post":
|
case "put":
|
{
|
// 启用倒带功能,就可以让 Request.Body 可以再次读取
|
request.EnableBuffering();
|
var stream = request.Body;
|
if (request.ContentLength != null)
|
{
|
byte[] buffer = new byte[request.ContentLength.Value];
|
var read = await stream.ReadAsync(buffer);
|
uLog.requestData = Encoding.UTF8.GetString(buffer);
|
}
|
request.Body.Position = 0;
|
break;
|
}
|
case "get":
|
case "delete":
|
uLog.requestData = HttpUtility.UrlDecode(request.QueryString.ObjectToString(), Encoding.UTF8);
|
break;
|
}
|
|
// 获取Response.Body内容
|
var originalBodyStream = context.Response.Body;
|
await using (var responseBody = new MemoryStream())
|
{
|
context.Response.Body = responseBody;
|
await _next(context);
|
uLog.responseBodyData = await GetResponse(context.Response);
|
await responseBody.CopyToAsync(originalBodyStream);
|
}
|
|
// 响应完成记录时间和存入日志
|
context.Response.OnCompleted(async () =>
|
{
|
_stopwatch.Stop();
|
|
uLog.opTime = _stopwatch.ElapsedMilliseconds + "ms";
|
uLog.endTime = DateTime.Now;
|
uLog.createTime = DateTime.Now;
|
//写入文件
|
if (middlewareRecordAccessLogsEnabledFileMode)
|
{
|
// 自定义log输出
|
var requestInfo = JsonConvert.SerializeObject(uLog);
|
Parallel.For(0, 1, e =>
|
{
|
LogLockHelper.OutSql2Log("RecordAccessLogs", "RecordAccessLogs" + DateTime.Now.ToString("yyyy-MM-dd-HH"), new[] { requestInfo + "," }, false);
|
});
|
}
|
//写入数据库
|
if (middlewareRecordAccessLogsEnabledDbMode)
|
{
|
await _sysUserOperationLogServices.InsertAsync(uLog);
|
}
|
});
|
}
|
else
|
{
|
await _next(context);
|
}
|
}
|
else
|
{
|
await _next(context);
|
}
|
}
|
|
|
/// <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;
|
}
|
}
|
|
}
|