审计日志中的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 (面向切面)的编程的缩写.他是和面向对象编程相对的一个概念.在面向对象的编程中,我们倾向于采用封装.继承.多态等概念,将一个个的功能在 ...
随机推荐
- rabbitMQ教程(三) spring整合rabbitMQ代码实例
一.开启rabbitMQ服务,导入MQ jar包和gson jar包(MQ默认的是jackson,但是效率不如Gson,所以我们用gson) 二.发送端配置,在spring配置文件中配置 <?x ...
- 海外ubuntu,lamp,ftp,phpmyadmin配置
海外ubuntu,lamp,ftp,phpmyadmin配置 1. 更换源 1.1 clean /etc/apt/sources.list file 1.2 Ubuntu Sources List G ...
- BeanShell Sample与控制台交互
应用的场景:业务当中涉及到一些敏感信息,如验证码,银行卡密码等或是动态变化的,不能直接写在脚本中,就需要通过控制台手动输入 如密码已键盘的方式输入,在控制台中以密码的方式显示 处理方法:添加 bean ...
- Python第二十天 shutil 模块 zipfile tarfile 模块
Python第二十天 shutil 模块 zipfile tarfile 模块 os文件的操作还应该包含移动 复制 打包 压缩 解压等操作,这些os模块都没有提供 shutil 模块shut ...
- K:java中的hashCode和equals方法
hashCode和equals方法是Object类的相关方法,而所有的类都是直接或间接的继承于Object类而存在的,为此,所有的类中都存在着hashCode和equals.通过翻看Object类 ...
- Python爬虫通过替换http request header来欺骗浏览器实现登录
以豆瓣为例,访问https://www.douban.com/contacts/list 来查看自己关注的人,要登录才能查看. 如果用requests.get()方法获取这个http,没登录只能抓取回 ...
- leetcode — word-break
import java.util.Arrays; import java.util.HashSet; import java.util.Set; /** * Source : https://oj.l ...
- c3p0使用记录
首先要导入c3p0包.c3p0下载解压后,lib目录下有三个包,使用mysql的话,只需要导入c3p0-0.9.5.2.jar,mchange-commons-java-0.2.11.jar. 要连接 ...
- SSH实战OA 11:BBS模块
<SSH实战OA>系列博客的系统管理.权限管理等内容后面再补上吧,先继续第三个模块:网上交流模块.网上交流主要做两个需求:论坛管理和论坛. BBS的一些基本术语: 板块:也叫做" ...
- gitlab勾住rocket chat
出于协作的要求, 需要在把gitlab的push event勾到rocket chat上面, 通知协作的其他人. BUT rocket chat提供的脚本没有具体的文件diff, so, 只好修改一下 ...