设为首页 加入收藏

TOP

[Abp vNext 源码分析] - 8. 审计日志(一)
2019-10-09 20:03:45 】 浏览:173
Tags:Abp vNext 源码 分析 审计 日志

一、简要说明

ABP vNext 当中的审计模块早在 依赖注入与拦截器一文中有所提及,但没有详细的对其进行分析。

审计模块是 ABP vNext 框架的一个基本组件,它能够提供一些实用日志记录。不过这里的日志不是说系统日志,而是说接口每次调用之后的执行情况(执行时间、传入参数、异常信息、请求 IP)。

除了常规的日志功能以外,关于 实体聚合 的审计字段接口也是存放在审计模块当中的。(创建人创建时间修改人修改时间删除人删除时间

二、源码分析

2.1. 审计日志拦截器

2.1.1 审计日志拦截器的注册

Volo.Abp.Auditing 的模块定义十分简单,主要是提供了 审计日志拦截器 的注册功能。下面代码即在组件注册的时候,会调用 AuditingInterceptorRegistrar.RegisterIfNeeded 方法来判定是否为实现类型(ImplementationType) 注入审计日志拦截器。

public class AbpAuditingModule : AbpModule
{
    public override void PreConfigureServices(ServiceConfigurationContext context)
    {
        context.Services.OnRegistred(AuditingInterceptorRegistrar.RegisterIfNeeded);
    }
}

跳转到具体的实现,可以看到内部会结合三种类型进行判断。分别是 AuditedAttributeIAuditingEnabledDisableAuditingAttribute

前两个作用是,只要类型标注了 AuditedAttribute 特性,或者是实现了 IAuditingEnable 接口,都会为该类型注入审计日志拦截器。

DisableAuditingAttribute 类型则相反,只要类型上标注了该特性,就不会启用审计日志拦截器。某些接口需要 提升性能 的话,可以尝试使用该特性禁用掉审计日志功能。

public static class AuditingInterceptorRegistrar
{
    public static void RegisterIfNeeded(IOnServiceRegistredContext context)
    {
        // 满足条件时,将会为该类型注入审计日志拦截器。
        if (ShouldIntercept(context.ImplementationType))
        {
            context.Interceptors.TryAdd<AuditingInterceptor>();
        }
    }

    private static bool ShouldIntercept(Type type)
    {
        // 首先判断类型上面是否使用了辅助类型。
        if (ShouldAuditTypeByDefault(type))
        {
            return true;
        }

        // 如果任意方法上面标注了 AuditedAttribute 特性,则仍然为该类型注入拦截器。
        if (type.GetMethods().Any(m => m.IsDefined(typeof(AuditedAttribute), true)))
        {
            return true;
        }

        return false;
    }

    //TODO: Move to a better place
    public static bool ShouldAuditTypeByDefault(Type type)
    {
        // 下面就是根据三种辅助类型进行判断,是否为当前 type 注入审计日志拦截器。
        if (type.IsDefined(typeof(AuditedAttribute), true))
        {
            return true;
        }

        if (type.IsDefined(typeof(DisableAuditingAttribute), true))
        {
            return false;
        }

        if (typeof(IAuditingEnabled).IsAssignableFrom(type))
        {
            return true;
        }

        return false;
    }
}

2.1.2 审计日志拦截器的实现

审计日志拦截器的内部实现,主要使用了三个类型进行协同工作。它们分别是负责管理审计日志信息的 IAuditingManager,负责创建审计日志信息的 IAuditingHelper,还有统计接口执行时常的 Stopwatch

整个审计日志拦截器的大体流程如下:

  1. 首先是判定 MVC 审计日志过滤器是否进行处理。
  2. 再次根据特性,和类型进行二次验证是否应该创建审计日志信息。
  3. 根据调用信息,创建 AuditLogInfoAuditLogActionInfo 审计日志信息。
  4. 调用 StopWatch 的计时方法,如果出现了异常则将异常信息添加到刚才构建的 AuditLogInfo 对象中。
  5. 无论是否出现异常,都会进入 finally 语句块,这个时候会调用 StopWatch 实例的停止方法,并统计完成执行时间。
public override async Task InterceptAsync(IAbpMethodInvocation invocation)
{
    if (!ShouldIntercept(invocation, out var auditLog, out var auditLogAction))
    {
        await invocation.ProceedAsync();
        return;
    }

    // 开始进行计时操作。
    var stopwatch = Stopwatch.StartNew();

    try
    {
        await invocation.ProceedAsync();
    }
    catch (Exception ex)
    {
        // 如果出现了异常,一样的将异常信息添加到审计日志结果中。
        auditLog.Exceptions.Add(ex);
        throw;
    }
    finally
    {
        // 统计完成,并将信息加入到审计日志结果中。
        stopwatch.Stop();
        auditLogAction.ExecutionDuration = Convert.ToInt32(stopwatch.Elapsed.TotalMilliseconds);
        auditLog.Actions.Add(auditLogAction);
    }
}

可以看到,只有当 ShouldIntercept() 方法返回 true 的时候,下面的统计等操作才会被执行。

protected virtual bool ShouldIntercept(
    IAbpMethodInvocation invocation, 
    out AuditLogInfo auditLog, 
    out AuditLogActionInfo auditLogAction)
{
    auditLog = null;
    auditLogAction = null;

    if (AbpCrossCuttingConcerns.IsApplied(invocation.TargetObject, AbpCrossCuttingConcerns.Auditing))
    {
        return false;
    }

    // 如果没有获取到 Scop,则返回 false。
    var audi
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇.net core 3.0 Signalr - 04 使用.. 下一篇关于部署版本遇到的---警告: 程序..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目