审计日志中的AOP
审计跟踪(也称为审核日志)是一个安全相关的时间顺序记录,记录这些记录的目的是为已经影响在任何时候的详细操作,提供程序运行的证明文件记录、源或事件
MVC
自定义一个过滤器
public class AuditFilter : IActionFilter
{
/// <summary>
/// 在执行操作方法后调用。
/// </summary>
/// <param name="filterContext"></param>
public void OnActionExecuted(ActionExecutedContext filterContext)
{
var auditData = AbpAuditFilterData.GetOrNull(filterContext.HttpContext);
if (auditData == null)
return;
auditData.Stopwatch.Stop();
var path = AppDomain.CurrentDomain.BaseDirectory + "log.txt";
if (filterContext.Exception != null)
File.AppendAllText(path,
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "异常:" + filterContext.Exception + "\r\n");
else
File.AppendAllText(path,
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "耗时:" +
Convert.ToInt32(auditData.Stopwatch.Elapsed.TotalMilliseconds) + "\r\n");
}
/// <summary>
/// 在执行操作方法之前调用。
/// </summary>
/// <param name="filterContext"></param>
public void OnActionExecuting(ActionExecutingContext filterContext)
{
var actionStopwatch = Stopwatch.StartNew();
AbpAuditFilterData.Set(
filterContext.HttpContext,
new AbpAuditFilterData(actionStopwatch)
);
}
}
定义一个数据存储
public class AbpAuditFilterData
{
private const string AbpAuditFilterDataHttpContextKey = "__AbpAuditFilterData";
public AbpAuditFilterData(
Stopwatch stopwatch)
{
Stopwatch = stopwatch;
}
public Stopwatch Stopwatch { get; }
public static void Set(HttpContextBase httpContext, AbpAuditFilterData auditFilterData)
{
GetAuditDataStack(httpContext).Push(auditFilterData);
}
public static AbpAuditFilterData GetOrNull(HttpContextBase httpContext)
{
var stack = GetAuditDataStack(httpContext);
return stack.Count <= 0
? null
: stack.Pop();
}
/// <summary>
/// 获取一个可变大小的后进先出 (LIFO) 集合
/// </summary>
/// <param name="httpContext"></param>
/// <returns></returns>
private static Stack<AbpAuditFilterData> GetAuditDataStack(HttpContextBase httpContext)
{
if (httpContext.Items[AbpAuditFilterDataHttpContextKey] is Stack<AbpAuditFilterData> stack)
return stack;
stack = new Stack<AbpAuditFilterData>();
httpContext.Items[AbpAuditFilterDataHttpContextKey] = stack;
return stack;
}
}
HomeController 如下
public class HomeController : Controller
{
public ActionResult Index()
{
var a = 0;
for (var i = 0; i < 10000; i++)
for (var j = 0; j < 10000; j++)
a = i - j;
ViewBag.A = a;
return View();
}
public ActionResult About()
{
var a = Convert.ToInt32("a");
ViewBag.Message = "Your application description page.";
return View();
}
}
访问home/index 日志记录如下:
2018-01-22 19:11:09耗时:342
访问home/about 日志记录如下:

Web Api
自定义过滤器
public class AuditFilter : IActionFilter
{
//
// 摘要:
// 获取或设置一个值,该值指示是否可以为单个程序元素指定多个已指示特性的实例。
//
// 返回结果:
// 如果可以指定多个实例,则为 true;否则为 false。默认值为 false。
public bool AllowMultiple => false;
/// <summary>
/// 异步执行筛选器操作
/// </summary>
/// <param name="actionContext"></param>
/// <param name="cancellationToken"></param>
/// <param name="continuation"></param>
/// <returns></returns>
public async Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
{
var method = actionContext.ActionDescriptor is ReflectedHttpActionDescriptor descriptor ? descriptor.MethodInfo : null;
var str = $"{actionContext.ActionDescriptor.ControllerDescriptor.ControllerType.Name}/{method?.Name}/{JsonConvert.SerializeObject(actionContext.ActionArguments)}";
var stopwatch = Stopwatch.StartNew();
var path = AppDomain.CurrentDomain.BaseDirectory + "log.txt";
try
{
return await continuation();
}
catch (Exception ex)
{
File.AppendAllText(path,
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " " + str + "异常:" + ex + "\r\n");
throw;
}
finally
{
stopwatch.Stop();
File.AppendAllText(path,
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " " + str + "耗时:" +
Convert.ToInt32(stopwatch.Elapsed.TotalMilliseconds) + "\r\n");
}
}
}
ValuesController代码如下
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
Thread.Sleep(new Random().Next(500, 1000));
return new[] { "Get" };
}
// GET api/values/5
public string Get(int id)
{
Thread.Sleep(new Random().Next(500, 1000));
return id + "";
}
[Route("api/values/GetError")]
public void GetError()
{
var a = Convert.ToInt32("a");
}
}
访问api/values 日志记录如下
2018-01-22 19:23:27 ValuesController/Get/{}耗时:978
访问api/values/1 日志记录如下
2018-01-22 19:24:21 ValuesController/Get/{"id":1}耗时:727
访问api/values/GetError 日志记录如下

Unity
自定义一个拦截器
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Interface)]
public class UnityAopAttribute : HandlerAttribute, ICallHandler
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return this;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
var s = new Stopwatch();
s.Start();
var result = getNext()(input, getNext);
if (result.Exception != null)
{
WriteLog(result.Exception.ToString());
//表示处理异常 Unity就不会抛出
result.Exception = null;
}
s.Stop();
WriteLog("方法:{0},参数:{1},耗时:{2}",
input.MethodBase.Name, JsonConvert.SerializeObject(input.Arguments), s.Elapsed.TotalMilliseconds);
return result;
}
private void WriteLog(string format, params object[] arg)
{
var path = AppDomain.CurrentDomain.BaseDirectory + "log.txt";
File.AppendAllText(path, string.Format(format, arg) + "\r\n");
}
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public bool WillExecute => false;
}
接口定义如下
public interface IOrderService
{
string GetOrder();
string GetOrderDetail();
}
实现如下
加上UnityAop标记
[UnityAop]
public class OrderService : IOrderService
{
public string GetOrder()
{
Thread.Sleep(new Random().Next(500, 1000));
return "GetOrder";
}
public string GetOrderDetail()
{
var i = Convert.ToInt32("a");
return i + "GetOrder";
}
}
注入及调用如下

示例代码:https://github.com/sunven/Abp1
Reference
审计日志中的AOP的更多相关文章
- Springboot中使用AOP统一处理Web请求日志
title: Springboot中使用AOP统一处理Web请求日志 date: 2017-04-26 16:30:48 tags: ['Spring Boot','AOP'] categories: ...
- Spring Boot中使用AOP统一处理Web请求日志
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是Spring框架中的一个重要内容,它通 ...
- (转)Spring Boot中使用AOP统一处理Web请求日志
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是Spring框架中的一个重要内容,它通 ...
- 在Delphi中应用AOP实现日志功能
AOP现在很火,网上有这许多支持AOP的框架,对于Delphi来说同样也有MeAOP.不过觉得这些框架太复杂了. 现在有一个系统,基本上都快结束了,整体上当然是没有采用什么AOP的框架.对于这样的系统 ...
- Spring Boot中使用AOP记录请求日志
这周看别人写的springboot后端代码中有使用AOP记录请求日志,以前没接触过,因此学习下. 一.AOP简介 AOP为Aspect Oriented Programming的缩写,意为:面向切面编 ...
- 46. Spring Boot中使用AOP统一处理Web请求日志
在之前一系列的文章中都是提供了全部的代码,在之后的文章中就提供核心的代码进行讲解.有什么问题大家可以给我留言或者加我QQ,进行咨询. AOP为Aspect Oriented Programming的缩 ...
- 转:Spring Boot中使用AOP统一处理Web请求日志
在spring boot中,简单几步,使用spring AOP实现一个拦截器: 1.引入依赖: <dependency> <groupId>org.springframewor ...
- Spring MVC 中使用AOP 进行统一日志管理--注解实现
1.AOP简介 AOP称为面向切面编程 AOP的基本概念 (1)Aspect(切面):通常是一个类,里面可以定义切入点和通知 (2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的 ...
- SpringBoot中使用AOP打印接口日志的方法(转载)
前言 AOP 是 Aspect Oriented Program (面向切面)的编程的缩写.他是和面向对象编程相对的一个概念.在面向对象的编程中,我们倾向于采用封装.继承.多态等概念,将一个个的功能在 ...
随机推荐
- centos7 卸载home 扩大root空间
=============================================== 2017/11/1_第1次修改 ccb_warlock == ...
- python自动安装mysql5.7
python自动安装mysql5.7 python版本:python2.6 centos版本:centos6.9 mysql版本:mysql5.7.19 安装目录路径和数据目录路径都是固定,当然也可以 ...
- centos7 安装solr
1 下载solr安装包 下载6.4.1版本 2.创建 存放数据的文件夹 solr_data 和 安装目录 solr_installation 3.进入solr的bin目录执行 /install_sol ...
- requireJS(版本是2.1.15)学习教程(一)
一:为什么要使用requireJS? 很久之前,我们所有的JS文件写到一个js文件里面去进行加载,但是当业务越来越复杂的时候,需要分成多个JS文件进行加载,比如在页面中head内分别引入a.js,b. ...
- 多线程-Timer重入
多线程Timer重入问题 由于使用多线程定时器,就会出现如果一个Timer处理没有完成,到了时间下一个照样会发生,这就会导致重入. 对付重入问题通常的办法是加锁,但是对于 Timer却不能简单的这样做 ...
- Android动画(一)-视图动画与帧动画
项目中好久没用过动画了,所以关于动画的知识都忘光了.知识总是不用则忘.正好最近的版本要添加比较炫酷的动画效果,所以也借着这个机会,写博客来整理和总结关于动画的一些知识.也方便自己今后的查阅. Andr ...
- Robot Framework学习笔记(六)------RIDE界面说明
RIDE是一款专门用来编辑Robot Framework用例的软件,用Python编写并且开源. 1.测试项目.测试套件Edit 标签 测试项目和测试套件所提供的 Edit 标签的功能是一样的. 在 ...
- JSON 序列化和解析
概述 JSON 即 (Javascript Object Notation,Javascript 对象表示法),是在Javascript中写结构化数据的方式.而JSON本身只是一种数据格式. 通常开发 ...
- node.js 之 Hello,World in Node !
创建一个js文件,把下面的内容粘贴进去,命名为helloworld.js. //加载 http 模块 var http = require("http"); //创建 http 服 ...
- [Micropython]TPYBoardV102 Dfu固件烧写教程
TPYBoardv10x固件烧写一直是大家比较关心的问题,上次教大家用SWD接口烧写TPYBoard的固件,这次教大家用另一种方式烧写我们TPYBoardv10x的固件,直接用dfu模式烧写固件. 用 ...