zoukankan      html  css  js  c++  java
  • 入门系列-审计日志

    维基百科: "审计跟踪(也称为审计日志)是一种安全相关的按时间顺序记录,记录集或记录目的和来源. 这种记录提供了在任何特定时间的操作,过程或事件产生影响活动顺序的文件证据 ".

    ABP框架提供一个可扩展的审计日志系统,自动化的根据约定记录审计日志,并提供配置控制审计日志的级别.

    一个审计日志对象(参见下面的审计日志对象部分)通常是针对每个web请求创建和保存的.包括;

    • 请求和响应的细节 (如URL,HTTP方法,浏览器信息,HTTP状态代码...等).
    • 执行的动作 (控制器操作和应用服务方法调用及其参数).
    • 实体的变化 (在Web请求中).
    • 异常信息 (如果在执行请求发生操作).
    • 请求时长 (测量应用程序的性能).

    启动模板已经将审计日志系统配置为适用于大多数应用程序. 本文档介绍了对审计日志系统更精细的控制.

    数据库提供程序支持

    UseAuditing()

    UseAuditing() 中间件应该被添加到ASP.NET Core请求管道,用于创建和保存审计日志. 如果你使用启动模板创建的应用程序,它已经默认添加.

    AbpAuditingOptions

    AbpAuditingOptions 是配置审计日志系统的主要options对象. 你可以在模块的 ConfigureServices 方法中进行配置:

    Configure<AbpAuditingOptions>(options =>
    {
        options.IsEnabled = false; //Disables the auditing system
    });
    

    这里是你可以配置的选项列表:

    • IsEnabled (默认值: true)启用或禁用审计系统的总开关. 如果值为 false,则不使用其他选项.
    • HideErrors (默认值: true)在保存审计日志对象时如果发生任何错误,审计日志系统会将错误隐藏并写入常规日志. 如果保存审计日志对系统非常重要那么将其设置为 false 以便在隐藏错误时抛出异常.
    • IsEnabledForAnonymousUsers (默认值: true)如果只想为经过身份验证的用户记录审计日志,请设置为 false.如果为匿名用户保存审计日志,你将看到这些用户的 UserId 值为 null.
    • AlwaysLogOnException(默认值: true)如果设置为 true,将始终在异常/错误情况下保存审计日志,不检查其他选项(IsEnabled 除外,它完全禁用了审计日志).
    • IsEnabledForGetRequests (默认值: false)HTTP GET请求通常不应该在数据库进行任何更改,审计日志系统不会为GET请求保存审计日志对象. 将此值设置为 true 可为GET请求启用审计日志系统.
    • ApplicationName:如果有多个应用程序保存审计日志到单一的数据库,使用此属性设置为你的应用程序名称区分不同的应用程序日志.
    • IgnoredTypes:审计日志系统忽略的 Type 列表. 如果它是实体类型,则不会保存此类型实体的更改. 在序列化操作参数时也使用此列表.
    • EntityHistorySelectors:选择器列表,用于确定是否选择了用于保存实体更改的实体类型. 有关详细信息请参阅下面的部分.
    • Contributors:AuditLogContributor 实现的列表. 贡献者是扩展审计日志系统的一种方式. 有关详细信息请参阅下面的"审计日志贡献者"部分。

    实体历史选择器

    保存您的所有实体的所有变化将需要大量的数据库空间. 出于这个原因审计日志系统不保存为实体的任何改变,除非你明确地对其进行配置.

    要保存的所有实体的所有更改,只需使用 AddAllEntities() 扩展方法.

    Configure<AbpAuditingOptions>(options =>
    {
        options.EntityHistorySelectors.AddAllEntities();
    });
    

    options.EntityHistorySelectors 实际上是一个类型谓词的列表,你可以写一个lambda表达式定义过滤器.

    下面的示例中与使用 AddAllEntities() 扩展方法效果相同:

    Configure<AbpAuditingOptions>(options =>
    {
        options.EntityHistorySelectors.Add(
            new NamedTypeSelector(
                "MySelectorName",
                type =>
                {
                    if (typeof(IEntity).IsAssignableFrom(type))
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
            )
        );
    });
    

    条件 typeof(IEntity).IsAssignableFrom(type) 对于任何实现 IEntity 接口的类(从技术上来这些都是你应用程序中的实体) 结果都为 true . 你可以根据自己的逻辑编写条件并返回 true 或 false.

    options.EntityHistorySelectors 是一种灵活动态的选择实体进行审计日志记录的方法. 另一种方法是为每个实体使用 Audited 和 DisableAuditing attribute。

    启用/禁用审计日志服务

    启用/禁用 Controllers & Actions

    默认所有的控制器动作都会被记录下来(有关GET请求,请参阅上面的 IsEnabledForGetRequests ).

    你可以使用 [DisableAuditing] 来禁用特定的控制器:

    [DisableAuditing]
    public class HomeController : AbpController
    {
        //...
    }
    

    使用 [DisableAuditing] 在action级别控制:

    public class HomeController : AbpController
    {
        [DisableAuditing]
        public async Task<ActionResult> Home()
        {
            //...
        }
    
        public async Task<ActionResult> OtherActionLogged()
        {
            //...
        }
    }

    启用/禁用 应用服务&方法

    应用服务也默认包含在审计日志中. 你可在服务或方法级别使用 [DisableAuditing]

    启用/禁用 其他服务

    可以为任何类型的类(注册到依赖注入并从依赖注入解析)启用审计日志,默认情况下仅对控制器和应用程序服务启用.

    对于任何需要被审计记录的类或方法都可以使用 [Audited] 和IAuditingEnabled.此外,您的类可以(直接或固有的)实现 IAuditingEnabled 接口以认启用该类的审计日志记录.

    启用/禁用 实体 & 属性

    以下情况下实体在实体更改审计日志记录中忽略实体;

    • 如果将实体类型添加到 AbpAuditingOptions.IgnoredTypes(如前所述),它在审计日志系统中被完全忽略.
    • 如果对象不是实体(没有直接或固有的实现 IEntity - 所有实体默认实现这个接口).
    • 如果实体访问级别不是public的.

    你可以使用 Audited 来启用实体更改审计日志:

    [Audited]
    public class MyEntity : Entity<Guid>
    {
        //...
    }
    

    或者禁用实体:

    [DisableAuditing]
    public class MyEntity : Entity<Guid>
    {
        //...
    }
    

    只有前面提到的 AbpAuditingOptions.EntityHistorySelector 选择实体时才有必要禁用审计日志记录.

    你可以仅禁用实体的某些属性的审计,以审计日志记录进行精细控制:

    [Audited]
    public class MyUser : Entity<Guid>
    {
        public string Name { get; set; }
    
        public string Email { get; set; }
    
        [DisableAuditing] //Ignore the Passoword on audit logging
        public string Password { get; set; }
    }

    审计日志系统保存 MyUser 实体的更改,出于安全的目的忽略 Password 属性.

    在某些情况下你可能要保存一些属性,但忽略所有其他属性. 为忽略的属性编写 [DisableAuditing] 将很乏味. 这种情况下将 [Audited] 用于所需的属性,使用 [DisableAuditing] 属性标记该实体:

    [DisableAuditing]
    public class MyUser : Entity<Guid>
    {
        [Audited] //Only log the Name change
        public string Name { get; set; }
    
        public string Email { get; set; }
    
        public string Password { get; set; }
    }
    

    IAuditingStore

    IAuditingStore 是一个接口,用于保存ABP框架的审计日志对象(下面说明). 如果需要将审计日志对象保存到自定义数据存储中,可以在自己的应用程序中实现 IAuditingStore 并在依赖注入系统替换。

    如果没有注册审计存储,则使用 SimpleLogAuditingStore. 它只是将审计对象写入标准日志系统

    审计日志模块已在启动模板中配置,它将审计日志对象保存到数据库中(支持多个数据库提供程序). 所以大多数时候你并不需要关心 IAuditingStore 是如何实现和使用的。

    审计日志对象

    默认为每个web请求创建一个审计日志对象,审计日志对象可以由以下关系图表示:

    auditlog-object-diagram

    • AuditLogInfo: 具有以下属性:
      • ApplicationName: 当你保存不同的应用审计日志到同一个数据库,这个属性用来区分应用程序.
      • UserId:当前用户的Id,用户未登录为 null.
      • UserName:当前用户的用户名,如果用户已经登录(这里的值不依赖于标识模块/系统进行查找).
      • TenantId: 当前租户的Id,对于多租户应用.
      • TenantName: 当前租户的名称,对于多租户应用.
      • ExecutionTime: 审计日志对象创建的时间.
      • ExecutionDuration: 请求的总执行时间,以毫秒为单位. 可以用来观察应用程序的性能.
      • ClientId: 当前客户端的Id,如果客户端已经通过认证.客户端通常是使用HTTP API的第三方应用程序.
      • ClientName: 当前客户端的名称,如果有的话.
      • ClientIpAddress: 客户端/用户设备的IP地址.
      • CorrelationId: 当前相关Id. 相关Id用于在单个逻辑操作中关联由不同应用程序(或微服务)写入的审计日志.
      • BrowserInfo: 当前用户的浏览器名称/版本信息,如果有的话.
      • HttpMethod: 当前HTTP请求的方法(GET,POST,PUT,DELETE ...等).
      • HttpStatusCode: HTTP响应状态码.
      • Url: 请求的URL.
    • AuditLogActionInfo: 一个 审计日志动作通常是web请求期间控制器动作或应用服务方法调用. 一个审计日志可以包含多个动作. 动作对象具有以下属性:
      • ServiceName:执行的控制器/服务的名称.
      • MethodName:控制器/服务执行的方法的名称.
      • Parameters:传递给方法的参数的JSON格文本.
      • ExecutionTime: 执行的时间.
      • ExecutionDuration: 方法执行时长,以毫秒为单位. 可以用来观察方法的性能.
    • EntityChangeInfo: 表示一个实体在Web请求中的变更. 审计日志可以包含0个或多个实体的变更. 实体变更具有以下属性:
      • ChangeTime: 当实体被改变的时间.
      • ChangeType:具有以下字段的枚举: Created(0), Updated(1)和 Deleted(2).
      • EntityId: 更改实体的Id.
      • EntityTenantId:实体所属的租户Id.
      • EntityTypeFullName: 实体的类型(类)的完整命名空间名称(例如Book实体的Acme.BookStore.Book.
    • EntityPropertyChangeInfo: 表示一个实体的属性的更改.一个实体的更改信息(上面已说明)可含有具有以下属性的一个或多个属性的更改:
      • NewValue: 属性的新值. 如果实体已被删除为 null.
      • OriginalValue:变更前旧/初始值. 如果实体是新创建为 null.
      • PropertyName: 实体类的属性名称.
      • PropertyTypeFullName:属性类型的完整命名空间名称.
    • Exception: 审计日志对象可能包含零个或多个异常. 可以得到失败请求的异常信息.
    • Comment:用于将自定义消息添加到审计日志条目的任意字符串值. 审计日志对象可能包含零个或多个注释.

    除了上面说明的标准属性之外,AuditLogInfoAuditLogActionInfo 和 EntityChangeInfo 对象还实现了IHasExtraProperties 接口,你可以向这些对象添加自定义属性.

    审计日志贡献者

    你可以创建类继承 AuditLogContributor类 来扩展审计系统,该类定义了 PreContribute 和 PostContribute 方法.

    唯一预构建的贡献者是 AspNetCoreAuditLogContributor 类,它设置HTTP请求的相关属性.

    贡献者可以设置 AuditLogInfo 类的属性和集合来添加更多信息。例:

    public class MyAuditLogContributor : AuditLogContributor
    {
        public override void PreContribute(AuditLogContributionContext context)
        {
            var currentUser = context.ServiceProvider.GetRequiredService<ICurrentUser>();
            context.AuditInfo.SetProperty(
                "MyCustomClaimValue",
                currentUser.FindClaimValue("MyCustomClaim")
            );
        }
    
        public override void PostContribute(AuditLogContributionContext context)
        {
            context.AuditInfo.Comments.Add("Some comment...");
        }
    }
    
    • context.ServiceProvider 可以从依赖注入系统中解析服务.
    • context.AuditInfo 可以用来访问当前审计日志的对象并进行操作.

    创建贡献者后,需要将其添加到 AbpAuditingOptions.Contributors 列表中:

    Configure<AbpAuditingOptions>(options =>
    {
        options.Contributors.Add(new MyAuditLogContributor());
    });

    IAuditLogScope & IAuditingManager

    本节介绍用于高级用例的 IAuditLogScope 和 IAuditingManager 服务。

    审计日志范围构建保存审计日志对象的环境范围(前面解释过). 默认审计日志中间件会为Web请求创建审计日志范围(请参阅上面的 UseAuditing() 部分)。

    获取当前审计日志范围

    上面提到,审计日志贡献者是操作审计日志对象的全局方法. 你可从服务中获得值.

    如果需要在应用程序的任意位置上操作审计日志对象,可以访问当前审计日志范围并获取当前审计日志对象(与范围的管理方式无关)。 例:

    public class MyService : ITransientDependency
    {
        private readonly IAuditingManager _auditingManager;
    
        public MyService(IAuditingManager auditingManager)
        {
            _auditingManager = auditingManager;
        }
    
        public async Task DoItAsync()
        {
            var currentAuditLogScope = _auditingManager.Current;
            if (currentAuditLogScope != null)
            {
                currentAuditLogScope.Log.Comments.Add(
                    "Executed the MyService.DoItAsync method :)"
                );
    
                currentAuditLogScope.Log.SetProperty("MyCustomProperty", 42);
            }
        }
    }

    总是检查 _auditingManager.Current 是否为空,因为它是在外部范围中控制的,在调用方法之前你不知道是否创建了审计日志范围.

    手动创建审计日志范围

    你很少需要手动创建审计日志的范围,但如果你需要,可以使用 IAuditingManager 创建审计日志的范围。例:

    public class MyService : ITransientDependency
    {
        private readonly IAuditingManager _auditingManager;
    
        public MyService(IAuditingManager auditingManager)
        {
            _auditingManager = auditingManager;
        }
    
        public async Task DoItAsync()
        {
            using (var auditingScope = _auditingManager.BeginScope())
            {
                try
                {
                    //Call other services...
                }
                catch (Exception ex)
                {
                    //Add exceptions
                    _auditingManager.Current.Log.Exceptions.Add(ex);
                }
                finally
                {
                    //Always save the log
                    await auditingScope.SaveAsync();
                }
            }
        }
    }
    

    您可以调用其他服务,它们可能调用其他服务,它们可能更改实体,等等。所有这些交互都保存为finally块中的一个审计日志对象。

    审计日志模块

    审计日志模块基本上实现了 IAuditingStore, 将审计日志对象保存到数据库中并支持多个数据库提供程序。默认此模块已添加到启动模板中。

  • 相关阅读:
    Spring框架(二)
    Spring概况(一)
    唉 规整规整 进阶目录
    网络编程 -- RPC实现原理 -- 目录
    基础大杂烩 -- 目录
    艺多不压身 -- 目录
    延伸 -- 分类 -- 目录
    Eclipse 快捷键
    全局
    深入浅出MySQL++数据库开发、优化与管理维护+第2版+唐汉明 -- 存储引擎
  • 原文地址:https://www.cnblogs.com/fxck/p/13076395.html
Copyright © 2011-2022 走看看