基于KYSharpCore+mysql的数据审计

该项目仅适用于本公司内部,所引用nuget不对外。

nuget引用版本:

KySharpCode 1.1 版本,

KYSharpCore.EntityFrameWork.MySql  3.1.7.4 版本

 

=====================================================================

数据审计包含范围很广,此次升级主要是针对应用内的数据审计。如在应用内对数据进行增删改操作的审计。

数据底层具体操作方式,详见:https://www.cnblogs.com/fei686868/articles/12221983.html

 

审计部分涉及的实体类包含(均在kysharpcore基类中)
AuditOperationEntry :主要记录操作的时间、用户、IP、url、客户端浏览器信息,该类嵌套AuditEntityEntry 数组。

AuditEntityEntry:主要记录实体信息,包含实体的名称、操作类型、主键,该类嵌套  AuditPropertyEntry数组。

AuditPropertyEntry:主要记录字段信息,包含字段的名称、类型、变更前后的数据。

 

其中AuditEntityEntry和AuditPropertyEntry的数据均在底层中获取。

 

所有需要审计的实体,均需要继承 IAudited 接口(命名空间:KYSharpCore.Audit),未继承的实体类,不会做审计。

 如:  public class Project : EntityBase<string>, IAudited

特别提示:存储审计的表对应的实体,不需要继承IAudited ,避免陷入死循环。

对于Update操作,获取数据需使用Track。若查询是AsNoTracking,将获取不到前后的变化。
当数据字段前后没变化时,也会获取审计实体信息,只是字段属性为null而已。实际存储,可根据需要自行处理。

 

下面详细讲讲用法:

1、定义一个action过滤器,主要用来获取AuditOperationEntry信息。例如:

 public class AuditOperationAttribute : ActionFilterAttribute
    {
        private AuditOperationEntry _auditOperationEntry;
        private IAuditStore _auditStore;
        public AuditOperationAttribute(AuditOperationEntry auditOperationEntry, IAuditStore auditStore)
        {
            _auditOperationEntry = auditOperationEntry;
            _auditStore = auditStore;


        }
        /// <inheritdoc />
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            // IServiceProvider provider = context.HttpContext.RequestServices;
   
            _auditOperationEntry.Ip = GetClientIp(context.HttpContext);
            _auditOperationEntry.UserAgent = context.HttpContext.Request.Headers["User-Agent"].FirstOrDefault();
            _auditOperationEntry.CreatedTime = DateTime.Now;

            _auditOperationEntry.UserId = "111"; //需要根据系统获取
            _auditOperationEntry.UserName = "张三";
            _auditOperationEntry.NickName = "三儿";
            _auditOperationEntry.PageUrl = context.HttpContext.Request.GetDisplayUrl();
            _auditOperationEntry.FunctionName = GetFunctionName(context);


        }

        /// <summary>
        /// 获取Area名
        /// </summary>
        public string GetFunctionName(ActionContext context)
        {
            string area = "";
            string controller = "";
            string action = "";
            if (context.RouteData.Values.TryGetValue("area", out object value))
            {
                area = (string)value;
                if (string.IsNullOrWhiteSpace(area))
                {
                    area = null;
                }
            }
            controller= context.RouteData.Values["controller"].ToString(); 
            action= context.RouteData.Values["action"].ToString();
            return (area+"/"+controller+"/"+action).Trim('/');
        }

    

        /// <summary>
        /// 获取客户端IP地址
        /// </summary>
        public static string GetClientIp(HttpContext context)
        {
            string ip = context.Request.Headers["X-Forwarded-For"].FirstOrDefault();
            if (string.IsNullOrEmpty(ip))
            {
                ip = context.Connection.RemoteIpAddress.ToString();
            }
            return ip;
        }

        ///// <inheritdoc />
        public override void OnResultExecuted(ResultExecutedContext context)
        {
            IServiceProvider provider = context.HttpContext.RequestServices;

            _auditOperationEntry.EndedTime = DateTime.Now;
         
            if (_auditStore != null&& _auditOperationEntry.EntityEntries.Any())
            {
                _auditStore.Save(_auditOperationEntry); //调用注入的审计存储方法
            }
        }

    }

2、在Startup.cs中增加注入,如下:

  public void ConfigureServices(IServiceCollection services)
        {
            //注册默认数据库
            services.AddKYSharpCoreDbContext(Configuration);
             services.AddScoped<AuditOperationEntry>(); //审计必须的
             services.AddScoped<IAuditStore, AuditStore>();//审计必须的,AuditStore类是对IAuditStore接口的实现,需要各应用端自行实现。
            services.AddControllersWithViews(
                o => { 
                    o.Filters.Add(typeof(AuditOperationAttribute)); //审计需要,注入过滤器获取登录信息
                
                });

        }

3、实现审计的存储

    /// <summary>
    /// 处理审计的存储
    /// </summary>
    public class AuditStore : IAuditStore
    {
        
        public void Save(AuditOperationEntry operationEntry)
        {
            //这里接收AuditOperationEntry对象参数,里面包含所有审计数据,自行存储到数据库。存储方式自行选择
        }

        public Task SaveAsync(AuditOperationEntry operationEntry, CancellationToken cancelToken = default)
        {
            //这里接收AuditOperationEntry对象参数,里面包含所有审计数据,自行存储到数据库。存储方式自行选择
            return null;
        }
    }

 

 

按照上述方式进行操作,即可对系统中所有继承IAudited接口的实体类对应的数据表的增删改操作记录审计日志。

 

posted @ 2020-11-18 17:24  黄明辉  阅读(229)  评论(0编辑  收藏  举报