审计日志中的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 (面向切面)的编程的缩写.他是和面向对象编程相对的一个概念.在面向对象的编程中,我们倾向于采用封装.继承.多态等概念,将一个个的功能在 ...
随机推荐
- lsattr 命令详解
lsattr 作用: 查看文件的第二扩展文件系统属性 选项: -a: 列出目录中的全部文件 -E: 显示设备属性的当前值, 从设备数据库中获得 -D: 显示属性的名称, 属性的默认值,描述和用户是否 ...
- java 分解质因数
算法目的:对一个正整数分解质因数 一.算法分析: 1.建立整数列表,保存求到的因数. 2.声明整数i=2,用以递增取模:整数m,用于临时保存n 3.建立while循环,i小于等于整数m时,判断m%i, ...
- 百度图表插件echart简单应用,简单配置一些要显示的样式及种类
从echart官网下载js,然后引入jq即可运行.足够简单应用了 关键词:echart控制:图标标题.数据标题.折线图.柱状图切换按钮.恢复刷新图表按钮.保存为图片按钮.坐标系控制.坐标数据.坐标倾斜 ...
- Oracle中session和processes的设置
欢迎和大家交流技术相关问题: 邮箱: jiangxinnju@163.com 博客园地址: http://www.cnblogs.com/jiangxinnju GitHub地址: https://g ...
- ABP架构学习系列一 整体项目结构及目录
本系列是基于aspnetboilerplate-0.8.4.0版本写的,其中原因是由于较高的版本太抽象难以理解和分析,对于还菜菜的我要花更多的时间去学习. abp的源码分析学习主要来源于 HK Zha ...
- TS Eslint规则说明
,//禁止使用alert confirm prompt ,//禁止使用数组构造器 ,//禁止使用按位运算符 ,//禁止使用arguments.caller或arguments.callee ,//禁止 ...
- opacity的背景透明&background中rgba的背景色透明
近期使用css实现了一个loading旋转加载的图片效果,类似gif动画 过程中,需要透明背景,但是图片不要透明 只要背景透明!只要背景透明!只要背景透明! 这里对透明模糊了,两种写法,模糊了 A: ...
- Java中Optional使用注意事项
前言 之前遇到过使用Optional之后带来的隐含bug,现在强调记录一下不好的用法,防止错用. Optional不能序列化,不能作为类的字段(field) 这点尤为重要,即类要纯粹.如果是POJO就 ...
- QtCreator 断点不起作用
使用QtCreator 调试程序时一直无法进入断点,断点根本不起作用. 解决方法: 打开.pro文件 将图中的release改为debug,再次调试运行就可以进入断点了.
- 扩充表字段长度,引发的意外KILLED/ROLLBACK
这一段时间,因为系统升级,新系统产生的数据长度,比原来的数据长度要长,所以说要扩充一下字段长度. ) --修改字段长度sql 在执行的时候,有这样一个情况. 例如Student表的Name字段长度是n ...