OperLogFilter.cs 5.07 KB
using Hh.Mes.Common.config;
using Hh.Mes.Common.Json;
using Hh.Mes.Service.Configure;
using Hh.Mes.Service.Logs;
using Hh.Mes.Service.SystemAuth;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Net.Http.Headers;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Dynamic;

namespace WebMvc.Aop
{
    /// <summary>
    ///  操作记录日志
    ///  action 请求前,请求后 
    /// </summary>
    public class OperLogFilter : ActionFilterAttribute
    {
        #region  property
        /// <summary>
        /// action 请求参数
        /// </summary>
        private string actionArguments { get; set; }

        private Stopwatch Stopwatch { get; set; }

        /// <summary>
        /// ioc 数据库访问层注入
        /// </summary>
        private readonly LogService _app;

        /// <summary>
        /// action操作 标识 (新增,删除,编辑,上传等等)
        /// </summary>
        private static Dictionary<string, string> operType { get; set; }

        /// <summary>
        /// 请求体上下文
        /// </summary>
        private HttpContext httpContext { get; set; }

        /// <summary>
        /// 用户信息
        /// </summary>
        private AuthStrategyContext currentUser { get; set; }

        #endregion

        public OperLogFilter(LogService  logService, IAuth authUtil)
        {
            _app = logService;
            operType = ConfigRead.GetInstance.GetOperType();
            currentUser = authUtil.GetCurrentUser();
        }

        public override void OnActionExecuting(ActionExecutingContext context)
        {
            base.OnActionExecuting(context);
            Stopwatch = new Stopwatch();
            Stopwatch.Start();
            httpContext = context.HttpContext;
            actionArguments = JsonConvert.SerializeObject(context.ActionArguments).Replace("\r", "").Replace("\n", "");
        }

        public override void OnActionExecuted(ActionExecutedContext context)
        {
            base.OnActionExecuted(context);
            Stopwatch.Stop();
            //Net Core 2.1Filter里面获取Controller、Action,请求方法,请求头部,请求参数
            //https://blog.csdn.net/mango_love/article/details/84992020
            var description = (ControllerActionDescriptor)context.ActionDescriptor;
            var actionName = description.ActionName;
            var otype = operType.ContainsKey(actionName) ? operType[actionName] : "其他";
            dynamic response;
            if (context.HttpContext.Request.Method.ToLower() == "get")
            {
                if (otype == "查看")
                {
                    response = "";
                }
                else
                {
                    var temp = context.Result as ObjectResult;
                    response = IsPropertyExist(temp, "Value") ? temp.Value : "在返回结果后发生了异常Get";
                }
            }
            else
            {
                dynamic result = context.Result;
                response = IsPropertyExist(result, "Value") ? result.Value : "在返回结果前发生了异常";
            }
            InserSysoperLog(otype, response, Stopwatch.Elapsed.TotalSeconds);
        }

        #region 自定义方法
        /// <summary>
        /// 写入日志 异步
        /// </summary>
        private void InserSysoperLog(string otype, dynamic response, double TotalSeconds)
        {
            bool isOk = response is string;
            if (!isOk) response = JsonHelper.Instance.Serialize(response);

            string url = httpContext.Request.Host + httpContext.Request.Path + httpContext.Request.QueryString;
            var dc = new Dictionary<string, object>
            {
                {"url", url},
                {"operType", otype},
                {"method", httpContext.Request.Method},
                {"request",httpContext.Request.Headers[HeaderNames.UserAgent].ToString()},
                {"parameter", actionArguments},

                {"response", response},
                {"totalMilliseconds", TotalSeconds},
                {"logTime", DateTime.Now},
                {"name", currentUser.User.Name},
                {"ip", httpContext.Connection.RemoteIpAddress.ToString()},
                {"createTime", DateTime.Now},
                {"createBy", currentUser.User.Account}
            };
            //字典 异步写入日志
            _app.GetContext().Insertable(dc).AS("sys_oper_log").ExecuteCommandAsync();
        }

        /// <summary>
        /// 动态类型 dynamic 是否存在某个属性
        /// </summary>
        public static bool IsPropertyExist(dynamic data, string propertyname)
        {
            if (data == null)
                return false;
            if (data is ExpandoObject)
                return ((IDictionary<string, object>)data).ContainsKey(propertyname);
            return data.GetType().GetProperty(propertyname) != null;
        } 
        #endregion
    }
}