在软件开发过程中,审计是一个重要的需求,它允许追踪数据的变化和用户的操作。为了实现这一需求,可以构建一个可重用的审计框架。本文将介绍如何构建这样一个框架,并将其插入到现有的代码中。
审计框架的目标是能够插入到现有的代码中,并且能够处理许多,如果不是所有的情况。然而,可能需要对应用程序代码进行一些更新,主要是配置相关的更改。
这个框架主要基于以下概念:
接下来,将简要介绍这些原则是如何在框架中使用的。在此之前,想先提一下审计表的结构:
模块名称 | 需要审计的功能模块名称 |
---|---|
表名称 | 需要审计的事务表名称 |
字段名称 | 需要审计的表中的字段名称 |
主键 | 需要审计的事务表记录的主键 |
旧值 | 字段的旧值 |
新值 | 字段的新值 |
用户 | 更新值的用户名称 |
时间戳 | 事务完成的时间 |
如果其他结构更适合需求,可以自定义这个框架。
需要在配置文件中设置一些设置以启用Unity和拦截。
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration"/>
<container>
<extension type="Interception"/>
<register type="AuditTracker.IAuditProcessor, AuditTracker" mapTo="AuditTracker.AuditProcessor, AuditTracker"/>
<register type="AuditTracker.IAuditRepository, AuditTracker" mapTo="AuditPOC.AuditRepository, AuditPOC"/>
<register type="AuditPOC.IAuditClient, AuditPOC" mapTo="AuditPOC.AuditClient, AuditPOC">
<interceptor type="InterfaceInterceptor"/>
<interceptionBehavior type="PolicyInjectionBehavior"/>
</register>
</container>
</unity>
配置文件的前几行将启用应用程序中的拦截。审计处理器是这个框架中的关键文件之一。稍后会介绍审计存储库。审计客户端是需要使用审计框架的应用程序。请注意,在Unity框架中注册审计客户端时,也添加了拦截器和拦截器行为设置。
审计属性需要添加到业务实体类字段中,以指示哪些字段需要审计。业务实体还需要实现IAuditableEntity接口。这个接口中只有一个方法,用于定义业务实体的主键值。
public class Employee : IAuditableEntity
{
private string _name = "Employee1";
private int _age = 35;
private int _empNum = 1001;
[AuditAttribute(ModuleName = "HR", TableName = "Employee", FieldName = "Name")]
public string Name
{
get { return this._name; }
set { this._name = value; }
}
public string PrimaryKeyIdentifier
{
get { return this._empNum.ToString(); }
set { throw new NotImplementedException(); }
}
}
接下来,需要在需要拦截审计的方法上定义“AuditCallHandler”属性。
关键是AuditCallHandlerAttribute继承自HandlerAttribute,因此Unity拦截将识别出这个属性被用于拦截。任何具有这个属性的方法都将被类(即AuditCallHandler)拦截,这是由属性类决定的。
[AuditCallHandler(false, TransactionType.Read, RequestType.CacheCurrentValue, 1)]
public Employee GetEmployeeDetails()
{
Employee emp = new Employee();
return emp;
}
[AuditCallHandler(false, TransactionType.Update, RequestType.SaveAuditDetails, 1)]
public void SaveEmployeeDetails(Employee emp)
{
}
AuditCallHandler将拦截调用,并且在特定方法操作被执行后,将执行其自己的逻辑,将详细信息传递给AuditProcessor。AuditCallHandler将实现ICallHandler和Invoke方法。Invoke方法将能够访问被拦截方法的输入参数以及输出值,这是关键。假设在获取方法的情况下,实体或实体列表将是输出,在保存/删除方法的情况下,要更新或删除的实体是方法的第一个输入。
审计处理器是一个简单的类,它将缓存数据库值或处理更新或删除的值。这个类将使用反射并识别自定义属性“Audit”以确定需要审计的字段。
审计处理器最终将调用一个存储库类来保存数据库中的审计详细信息。已经将这个控制权留给了应用程序,以决定如何处理审计实体。存储库类应该实现IAuditRepository,并应该像上面所示在配置文件中注册。
如果要将这个框架插入到应用程序代码中,需要进行以下更改:
请注意,没有对这个代码进行任何性能检查,所以请谨慎使用。同时,并不声称这个代码是以最佳方式编写的,并且能够处理所有场景。根据需求开发了这个特定的代码。其他人可以自由下载代码并对其进行优化或更改。