.Net Core 审计日志实现
2020-12-27 22:07
141 查看
前言:
近日在项目协同开发过程中出现了问题,数据出现了异常;其他人员怀疑项目数据丢失程序存在问题。于是通过排查程序提供的审计日志最终还原了当时操作及原因。
可见审计日志在排查、定位问题是相当有用的,那么在.Net Core 如何来实现审计日志呢?
接下来一步步来实现效果
一、审计日志定义及作用
审计日志:
维基百科: “审计跟踪(也叫审计日志)是与安全相关的按照时间顺序的记录,记录集或者记录源,它们提供了活动序列的文档证据,这些活动序列可以在任何时间影响一个特定的操作,步骤或其他”
作用:
1、快速定位问题耗时及性能情况
2、记录调用时环境信息:如浏览器、参数等
二、.Net Core 中实现审计日志
那么怎么实现审计日志呢?其实核心思想很简单。包含以下步骤:
- 获取调用接口方法时相关信息
- 记录当前接口耗时情况
- 保存审计日志信息到数据库中
那么如何获取调用接口时相关信息呢?.Net Core中可以使用:过滤器、拦截器 实现。
本次示例中将采用过滤器实现审计日志实现功能;主要流程如下
-
定义审计日志信息:
public class AuditInfo { /// <summary> /// 调用参数 /// </summary> public string Parameters { get; set; } /// <summary> /// 浏览器信息 /// </summary> public string BrowserInfo { get; set; } /// <summary> /// 客户端信息 /// </summary> public string ClientName { get; set; } /// <summary> /// 客户端IP地址 /// </summary> public string ClientIpAddress { get; set; } /// <summary> /// 执行耗时 /// </summary> public int ExecutionDuration { get; set; } /// <summary> /// 执行时间 /// </summary> public DateTime ExecutionTime { get; set; } /// <summary> /// 返回内容 /// </summary> public string ReturnValue { get; set; } /// <summary> /// 异常对象 /// </summary> public Exception Exception { get; set; } /// <summary> /// 方法名 /// </summary> public string MethodName { get; set; } /// <summary> /// 服务名 /// </summary> public string ServiceName { get; set; } /// <summary> /// 调用者信息 /// </summary> public string UserInfo { get; set; } /// <summary> /// 自定义数据 /// </summary> public string CustomData { get; set; } }
- 实现审计日志过滤器
using AuditLogDemo.Models; using AuditLogDemo.Services; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Threading.Tasks; namespace AuditLogDemo.Fliters { public class AuditLogActionFilter : IAsyncActionFilter { /// <summary> /// 审计日志服务对象 /// </summary> private readonly IAuditLogService _auditLogService; /// <summary> /// 登录用户 /// </summary> private readonly ISession _Session; /// <summary> /// 日志记录 /// </summary> private readonly ILogger<AuditLogActionFilter> _logger; public AuditLogActionFilter( IAuditLogService auditLogService, ISession Session, ILogger<AuditLogActionFilter> logger ) { _Session = Session; _logger = logger; _auditLogService = auditLogService; } public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { // 判断是否写日志 if (!ShouldSaveAudit(context)) { await next(); return; } //接口Type var type = (context.ActionDescriptor as ControllerActionDescriptor).ControllerTypeInfo.AsType(); //方法信息 var method = (context.ActionDescriptor as ControllerActionDescriptor).MethodInfo; //方法参数 var arguments = context.ActionArguments; //开始计时 var stopwatch = Stopwatch.StartNew(); var auditInfo = new AuditInfo { UserInfo = _Session?.Id, ServiceName = type != null ? type.FullName.TruncateWithPostfix(EntityDefault.FieldsLength250) : "", MethodName = method.Name.TruncateWithPostfix(EntityDefault.FieldsLength250), ////请求参数转Json Parameters = JsonConvert.SerializeObject(arguments), ExecutionTime = DateTime.Now, BrowserInfo = context.HttpContext.Request.Headers["User-Agent"].ToString().TruncateWithPostfix(EntityDefault.FieldsLength250), ClientIpAddress = context.HttpContext.Connection.RemoteIpAddress.ToString().TruncateWithPostfix(EntityDefault.FieldsLength50), //ClientName = _clientInfoProvider.ComputerName.TruncateWithPostfix(EntityDefault.FieldsLength100), Id = Guid.NewGuid().ToString() }; ActionExecutedContext result = null; try { result = await next(); if (result.Exception != null && !result.ExceptionHandled) { auditInfo.Exception = result.Exception; } } catch (Exception ex) { auditInfo.Exception = ex; throw; } finally { stopwatch.Stop(); auditInfo.ExecutionDuration = Convert.ToInt32(stopwatch.Elapsed.TotalMilliseconds); if (result != null) { switch (result.Result) { case ObjectResult objectResult: auditInfo.ReturnValue = JsonConvert.SerializeObject(objectResult.Value); break; case JsonResult jsonResult: auditInfo.ReturnValue = JsonConvert.SerializeObject(jsonResult.Value); break; case ContentResult contentResult: auditInfo.ReturnValue = contentResult.Content; break; } } Console.WriteLine(auditInfo.ToString()); //保存审计日志 await _auditLogService.SaveAsync(auditInfo); } } /// <summary> /// 是否需要记录审计 /// </summary> /// <param name="context"></param> /// <returns></returns> private bool ShouldSaveAudit(ActionExecutingContext context) { if (!(context.ActionDescriptor is ControllerActionDescriptor)) return false; var methodInfo = (context.ActionDescriptor as ControllerActionDescriptor).MethodInfo; if (methodInfo == null) { return false; } if (!methodInfo.IsPublic) { return false; } if (methodInfo.GetCustomAttribute<AuditedAttribute>() != null) { return true; } if (methodInfo.GetCustomAttribute<DisableAuditingAttribute>() cf0 != null) { return false; } var classType = methodInfo.DeclaringType; if (classType != null) { if (classType.GetTypeInfo().GetCustomAttribute<AuditedAttribute>() != null) { return true; } if (classType.GetTypeInfo().GetCustomAttribute<AuditedAttribute>() != null) { return false; } } return false; } } }
该内容为实现审计日志功能主要逻辑,通过过滤器获取当前执行控制器、方法判断是否需要记录审计日志;其他请求参数、客户端ip等相关基本信息组成审计日志对象,并记录调用时间。
- 注册过滤器
public void ConfigureServices(IServiceCollection services) { services.AddControllers(options => { options.Filters.Add(typeof(AuditLogActionFilter)); }); //审计日志存储 services.AddDbContext<AuditLogDBContent>(options => { string conn = Configuration.GetConnectionString("LogDB"); options.UseSqlite(conn); }); }
到此审计日志主要逻辑已经实现完成。是不是很简单
三、总结
回过头来看,在.net co 10d8 re 中需要统一监控或过滤时,可以采用过滤器(Filter)或拦截器来实现相关效果
.Net Core中 Filter 常件的有:Authorization Filter(认证过滤器),Resource Filter(资源过滤器),Exception Filter(异常过滤器),Action Filter(方法过滤器),Result Filter(结果过滤器)
相关文章推荐
- XAF 14.1 DC 实现自定审计日志信息
- 使用拦截器实现审计日志
- 如何实现对Informix进行日志审计
- .NET Core微服务之基于Exceptionless实现分布式日志记录
- 如何实现对Informix进行日志审计
- 微服务日志之.NET Core使用NLog通过Kafka实现日志收集
- AOP基本概念、AOP底层实现原理、AOP经典应用【事务管理、异常日志处理、方法审计】
- struts拦截器+注解实现网络安全要求中的日志审计功能
- EF利用重写SaveChanges()方法实现 审计日志记录
- .Net Core中间件和过滤器实现错误日志记录
- C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志
- .net core系列之《对AOP思想的理解及使用AspectCore实现自定义日志拦截》
- [置顶] 使用struts拦截器+注解实现网络安全要求中的日志审计功能
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- 基于spring boot实现空属性赋值和aspect日志
- 数据挖掘项目之---通过对web日志的挖掘来实现内容推荐系统
- 安装oracle11的时候 提示ORA-28056 未能将审计记录写入windows事件日志,这是怎么回事啊
- 使用SQLServer代理实现定时清除数据库日志
- python操作ssh实现服务器日志下载的方法
- 实现loganalyzer-日志管理