1. 程式人生 > 實用技巧 >asp.net core ActionExecutedContext 獲取Request.Body內容

asp.net core ActionExecutedContext 獲取Request.Body內容

實體類:

 public class ApiActionDescriptorModel:ICloneable
    {
        
        public string ActionName { get; set; } 

        public string ControllerName { get; set; } 

        public ApiParameterDescriptorModel[] Parameters { get; set; } 

        public ApiReturnAttributeModel[] apiReturnAttributes { get; set; } 

        public string RequestIp { get; set; } 

        public string HttpMethod { get; set; } 

        public string RequestPort { get; set; }

        public long ExecutTime { get; set; } 

        public string Operator { get; set; } 

        public DateTime OperaTime { get; set; } 

        public string RequestBody { get; set; } 

        public string QueryString { get; set; }
        
        public string ResposeBody { get; set; } 

        public int ResposeStatusCode { get; set; } 

        public string UserId { get; set; }

        public object Clone()
        {
            return new ApiActionDescriptorModel
            {
                ActionName = this.ActionName,
                RequestIp = this.RequestIp,
                HttpMethod = this.HttpMethod,
                RequestPort = this.RequestPort,
                ExecutTime = this.ExecutTime,
                Parameters = this.Parameters.Select(t => (ApiParameterDescriptorModel)t.Clone()).ToArray()
            };
        }
    }

  過濾器:

public class ExceptionFilter : IExceptionFilter
    {
        [Import]
        private ILoggerHelper loggerHelper { get; set; }

        public ExceptionFilter(IoC ioc) 
        {
            ioc.Compose(this);
        }

        public void OnException(ExceptionContext context)
        {
            if (context.ExceptionHandled == false)
            {
                var jsonobj = Dr.Soc.Common.Helpers.JsonResult.Error(context.Exception.Message);
                context.Result = new JsonResult(jsonobj);
            }
            loggerHelper.Error($"全域性捕獲異常:" + context.Exception.ToString()+"====="+
                "入參引數:"+ GetExceptionRequestBody(context)+context?.HttpContext?.Request?.QueryString);
            
            context.ExceptionHandled = true;
        }

        public Task OnExceptionAsync(ExceptionContext context)
        {
            OnException(context);
            return Task.CompletedTask;
        }

        private string GetExceptionRequestBody(ExceptionContext context)
        {
            string requestBody = "";
            if (context != null)
            {
                var request = context?.HttpContext?.Request;
                if (request != null)
                {
                    request.Body.Position = 0;
                    StreamReader stream = new StreamReader(request.Body);
                    requestBody = stream.ReadToEnd();
                    request.Body.Position = 0;
                }
            }
            return requestBody;
        }

    }

  

 public class ActionFilter : IActionFilter
    {
        private Stopwatch timer;

        [Import]
        private IAduitService aduitService { get; set; }

        public ActionFilter(IoC ioc)
        {
            ioc.Compose(this);
        }

        public void OnActionExecuting(ActionExecutingContext context)
        {
            this.timer = new Stopwatch();
            this.timer.Start();
        }

        public void OnActionExecuted(ActionExecutedContext context)
        {
            this.timer.Stop();
            aduitService.HandleApiAction(GetActionDescriptor(context));
        }

        private ApiActionDescriptorModel GetActionDescriptor(ActionExecutedContext context)
        {
            ApiActionDescriptorModel descriptor = new ApiActionDescriptorModel();
   
            var userInfo= ((System.Security.Claims.ClaimsIdentity)context.HttpContext.User.Identity).Claims?.ToList();
            if (context != null)
            {
                descriptor.ActionName = ((ControllerActionDescriptor)context.ActionDescriptor)?.ActionName;
                descriptor.ControllerName = ((ControllerActionDescriptor)context.ActionDescriptor)?.ControllerName;
                descriptor.RequestIp = context.HttpContext.Request.Host.Host.ToString();
                descriptor.RequestPort = context.HttpContext.Request.Host.Port.ToString();
                descriptor.HttpMethod = context.HttpContext.Request.Method.ToString();
                descriptor.ExecutTime = this.timer.ElapsedMilliseconds;
                descriptor.Operator = userInfo?.Where(t => t.Type == "UserName")?.FirstOrDefault()?.Value;
                descriptor.UserId = userInfo?.Where(t => t.Type == "UserId")?.FirstOrDefault()?.Value;
                descriptor.OperaTime = DateTime.Now;
                descriptor.RequestBody = ReadActionExcutedRequestBody(context);
                descriptor.QueryString = context.HttpContext.Request?.QueryString.ToString();
                descriptor.ResposeBody = GetActionExcutedResponseBody(context);
                descriptor.ResposeStatusCode = context.HttpContext.Response.StatusCode;
            }

            return descriptor;
        }

        private string ReadActionExcutedRequestBody(ActionExecutedContext context)
        {
            string requestBody = "";
            if (context != null)
            {
                var request = context.HttpContext.Request;
                request.Body.Position = 0;
                StreamReader stream = new StreamReader(request.Body);
                requestBody = stream.ReadToEnd();
                request.Body.Position = 0;
            }
            return requestBody;
        }

        private string GetActionExcutedResponseBody(ActionExecutedContext context)
        {
            string responseBody = "";
            if (context.Result != null)
            {
                if (context.Result is ObjectResult)
                    responseBody = JsonConvert.SerializeObject(((ObjectResult)context.Result).Value);
                if (context.Result is JsonResult)
                    responseBody = JsonConvert.SerializeObject(((JsonResult)context.Result).Value);
            }
            return responseBody;
        }
    }

在startup中註冊:

app.Use(next => new RequestDelegate(
                async context =>
                {
                    context.Request.EnableBuffering();
                    await next(context);
                }
                ));

  就可以在請求之後獲取到請求體了。

public async Task<bool> HandleApiAction(ApiActionDescriptorModel apiActionDescriptorModel)
        {
            bool result = false;
            var cacheAuditRule = auditRuleLoader.GetAllAuditRule();
            try
            {
                if (cacheAuditRule == null || cacheAuditRule.Count == 0) return result;

                if (string.IsNullOrEmpty(apiActionDescriptorModel?.RequestBody)
                || string.IsNullOrEmpty(apiActionDescriptorModel?.ActionName)
                || string.IsNullOrEmpty(apiActionDescriptorModel?.ControllerName)
                || string.IsNullOrEmpty(apiActionDescriptorModel?.HttpMethod)) return result;

                List<AuditModel> list = HandleApiAction(apiActionDescriptorModel, cacheAuditRule);

                if (list == null || list.Count == 0) return result;

                result = await auditDataAccessor.BatchAddAudit(list.Adapt<List<AuditDao>>()).ConfigureAwait(false);
                return result;
            }
            catch (Exception ex)
            {
                loggerHelper.Error(apiActionDescriptorModel.ControllerName + apiActionDescriptorModel.ActionName + "插入審計失敗,失敗原因:" + ex.ToString());
                return result;
            }
        }

        private List<AuditModel> HandleApiAction(ApiActionDescriptorModel apiActionDescriptorModel, List<AuditRuleModel> auditRuleModels)
        {
            int apiEnum = (int)EnumHelper.GetValue(typeof(HttpMethodEnum), apiActionDescriptorModel.HttpMethod?.ToLower());

            var auditRuleModel = auditRuleModels.Where(t => t.ControllerName == apiActionDescriptorModel.ControllerName
             && t.ActionName == apiActionDescriptorModel.ActionName
             && t.HttpMethod == apiEnum)?.FirstOrDefault();

            List<AuditModel> list = new List<AuditModel>();
            if (auditRuleModel == null) return list;

            if (!string.IsNullOrEmpty(auditRuleModel.AuditRuleDescr))
            {
                var audits = GetAudits(apiActionDescriptorModel, auditRuleModel);

                if (audits != null && audits.Count > 0)
                    list = GetAudits(apiActionDescriptorModel, auditRuleModel, audits);
            }

            return list;
        }

        private List<AuditModel> GetAudits(ApiActionDescriptorModel apiActionDescriptorModel, AuditRuleModel auditRuleModel, List<string> audits)
        {
            List<AuditModel> auditModels = new List<AuditModel>();
            int responseCode = GetResponseCode(apiActionDescriptorModel?.ResposeBody);
            for (int i = 0; i < audits.Count; i++)
            {
                AuditModel auditModel = new AuditModel();
                auditModel.UserName = apiActionDescriptorModel.Operator;
                auditModel.AddTime = apiActionDescriptorModel.OperaTime;
                auditModel.Ip = apiActionDescriptorModel.RequestIp.Replace("localhost", "127.0.0.1");
                auditModel.ResponseCode = responseCode;
                auditModel.ModelType = auditRuleModel.ModelType;
                auditModel.Type = EnumHelper.Parse<OperateType>(auditRuleModel.OperateType);
                auditModel.IncidenceLevel = EnumHelper.Parse<IncidenceLevel>(auditRuleModel.IncidenceLevel);
                auditModel.Detail = audits[i];
                auditModel.UserId = apiActionDescriptorModel.UserId;
                auditModel.UserName = apiActionDescriptorModel.Operator;

                auditModels.Add(auditModel);
            }
            return auditModels;
        }

        private List<string> GetAudits(ApiActionDescriptorModel apiActionDescriptorModel, AuditRuleModel auditRuleModel)
        {
            var jsonDics = GetKeyValues(apiActionDescriptorModel.RequestBody);
            var urlDics = GetKeyValues(apiActionDescriptorModel.QueryString);

            foreach (var item in urlDics)
            {
                if (item != null && item.Count > 0)
                {
                    foreach (var keyValue in item)
                        jsonDics.ForEach(t => t.Add(keyValue.Key, keyValue.Value));
                }
            }

            List<string> audits = new List<string>();

            foreach (var item in jsonDics)
            {
                var ruleStr = auditRuleModel.AuditRuleDescr;
                string[] rules = RegularHelper.FindByRegexRemoveRegexs(ruleStr, "【\\${.*?}】", "[【】\\${}]+");
                if (rules.Length > 0)
                {
                    for (int i = 0; i < rules.Length; i++)
                    {
                        if (!item.Keys.Contains(rules[i])) continue;

                        string value = item[rules[i]];
                        if (rules[i] == auditRuleModel.AssetIdMappingField)
                            value = assetAccountLoader.GetAssetCacheByCode(value).Name;

                        ruleStr = ruleStr.Replace("${" + rules[i] + "}", value);
                    }
                }

                audits.Add(ruleStr);
            }
            return audits;
        }

        private List<Dictionary<string, string>> GetKeyValues(string txt)
        {
            List<Dictionary<string, string>> dics = new List<Dictionary<string, string>>();

            if (JsonHelper.StringIsJson(txt))
            {
                string text = RegularHelper.FindFirstByRegex(txt, @"^\[.*?\]$");

                List<JObject> jObjects = string.IsNullOrEmpty(text)
                    ? new List<JObject>() { JsonConvert.DeserializeObject<JObject>(txt) }
                    : JsonConvert.DeserializeObject<List<JObject>>(txt);

                foreach (var item in jObjects)
                    dics.Add(item.Properties().ToDictionary(x => x.Name, y => y.Value.ToString()));
            }
            else
            {
                NameValueCollection collection = HttpUtility.ParseQueryString(txt);
                var dic = new Dictionary<string, string>();
                foreach (var item in collection.AllKeys)
                    dic.Add(item, collection[item]);

                dics.Add(dic);
            }
            return dics;
        }

        private static int GetResponseCode(string resposeBody)
        {
            int responseCode = -1;
            int.TryParse(RegularHelper.FindContentBetweenTwoRegex(resposeBody, "code\":", ","), out responseCode);
            return responseCode;
        }

        private List<AuditModel> HandleIsJsonActionToAudit(ApiActionDescriptorModel apiActionDescriptorModel, AuditRuleModel auditRuleModel)
        {
            string text = RegularHelper.FindFirstByRegex(apiActionDescriptorModel.RequestBody, @"^\[.*?\]$");

            List<JObject> jObjects = null;
            if (!string.IsNullOrEmpty(text))
                jObjects = JsonConvert.DeserializeObject<List<JObject>>(apiActionDescriptorModel.RequestBody);
            else
                jObjects = new List<JObject>() { JsonConvert.DeserializeObject<JObject>(apiActionDescriptorModel.RequestBody) };

            string[] rules = RegularHelper.SplitByRegex(auditRuleModel.AuditRuleDescr, "【.*?】");

            List<AuditModel> list = null;

            for (int i = 0; i < jObjects.Count; i++)
            {
                list = new List<AuditModel>(){
                    new AuditModel()
                    {
                        UserName=apiActionDescriptorModel.Operator,
                        ModelType=auditRuleModel.ModelType,
                        Type =EnumHelper.Parse<OperateType>(auditRuleModel.OperateType),
                        IncidenceLevel =EnumHelper.Parse<IncidenceLevel>(auditRuleModel.IncidenceLevel),
                        UserId=apiActionDescriptorModel.UserId,
                        Detail = GetAuditDetailByRuleRule(jObjects[i], rules).ToString(),
                        AddTime = apiActionDescriptorModel.OperaTime,
                        Ip = apiActionDescriptorModel.RequestIp.Replace("localhost","127.0.0.1"),
                        ResponseCode=GetResponseCode(apiActionDescriptorModel?.ResposeBody),
                    }
                };
            }

            return list;
        }

        private List<AuditModel> HandleNotJsonActionToAduit(ApiActionDescriptorModel apiActionDescriptorModel, AuditRuleModel auditRuleModel)
        {
            string[] rules = RegularHelper.SplitByRegex(auditRuleModel.AuditRuleDescr, "【.*?】");

            List<AuditModel> list = null;
            if (rules.Length >= 2)
            {
                list = new List<AuditModel>(){
                    new AuditModel()
                    {
                         UserName=apiActionDescriptorModel.Operator,
                         ModelType=auditRuleModel.ModelType,
                         Type =EnumHelper.Parse<OperateType>(auditRuleModel.OperateType),
                         IncidenceLevel =EnumHelper.Parse<IncidenceLevel>(auditRuleModel.IncidenceLevel),
                         Detail = GetAuditDetailByRuleRule(apiActionDescriptorModel.RequestBody,rules).ToString(),
                         AddTime = apiActionDescriptorModel.OperaTime,
                         Ip = apiActionDescriptorModel.RequestIp.Replace("localhost","127.0.0.1"),
                         ResponseCode=GetResponseCode(apiActionDescriptorModel?.ResposeBody),
                    }
                };
            }
            return list;
        }

        private StringBuilder GetAuditDetailByRuleRule(string text, string[] rules)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(rules[0]);

            for (int i = 1; i < rules.Length; i++)
                sb.Append(
                    RegularHelper.RegexReplace(
                    rules[i],
                    "【.*?】",
                    "【" + RegularHelper.FindContentBetweenTwoRegex(
                        text, "[\\?&]" + RegularHelper.FindContentBetweenTwoRegex(rules[i], @"【\${", "}】") + "=", "(&|$)") + "】"
                        ));

            return sb;
        }

        private StringBuilder GetAuditDetailByRuleRule(JObject jObject, string[] rules)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(rules[0]);
            for (int i = 1; i < rules.Length; i++)
            {
                try
                {
                    sb.Append(
                        RegularHelper.RegexReplace(rules[i],
                        "【.*?】",
                    "【" + jObject[RegularHelper.FindContentBetweenTwoRegex(rules[i], @"【\${", "}】")].ToString() + "】"
                    ));
                }
                catch (Exception ex)
                {
                    loggerHelper.Error("在" + rules[i] + "查詢失敗,具體原因:" + ex.ToString());
                    throw;
                }
            }

            return sb;
        }

  

 public static string[] FindByRegexRemoveRegexs(string html, string strReg, string remReg)
        {
            string[] strs = FindByRegex(html, strReg);
            List<string> result = new List<string>();
            if (strs.Length > 0)
            {
                for (int i = 0; i < strs.Length; i++)
                    result.Add(RemoveByRegex(strs[i], remReg));
            }
            return result.ToArray();
        }