当前位置: 首页 > 工具软件 > Audit4j > 使用案例 >

AuditLog配置详解

邢凯歌
2023-12-01

介绍

auditLog采用Audit4j进行了简单的封装。

配置

在applicaton-.yml中添加auditLog的配置,配置参数如下:

# auditLog配置
audit4j:
  db-handler:
    # auditLog记录时否分表. 对于业务不是很复杂的应用,一般设置成false即可
    separate: false
    # 是否用内置的数据库记录.一般都是用自己的业务数据库,所以设置为false
    embedded: false
    # 默认的表名
    default_table_name: audit
    # 以下是auditLog数据库连接的一些配置;auditLog和业务的数据库不共用连接
    db_connection_type: pooled
    db_pool_connectionTimeout: 30000
    db_pool_maximumPoolSize: 2
    db_pool_minimumIdle: 1
    db_driver: com.mysql.jdbc.Driver
    db_url: jdbc:mysql://test.yuxisoft.cn:3306/loreal?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=true&allowMultiQueries=true
    db_user: root
    db_password: yuxisoft
  # auditLog写日志文件的位置,app需要替换成应用的名称
  log:
    file:
      location: var/log/app/audit

数据库创建

separate设置为false

在separate设置为false情况下,Audit4j是使用默认使用名称为audit的表来记录(可以通过default_table_name来设置)。如果audit表不存在,会自动创建,创建的字段包括identifier, timestamp, actor, origin, action, elements, 字符集是utf-8格式。

建议自己先创建好audit表,并根据业务情况设置字段长度和类型。比如actor或者elements中有特殊符号,例如emoji表情,字符集需要设置成utf8mb4,如下:

CREATE TABLE `audit` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `identifier` varchar(200) NOT NULL,
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `actor` varchar(200) CHARACTER SET utf8mb4 NOT NULL COMMENT '保存账号,名称,权限ID,数据权限ID',
  `origin` varchar(200) DEFAULT NULL,
  `action` varchar(200) NOT NULL,
  `elements` longtext CHARACTER SET utf8mb4,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8 COMMENT='auditLog';

separate设置为true

separate设置为true情况下,在记录日志的时可以指定表前缀,例如在@Audit指定repository=login,该auditEvent就会记录在login_audit表中。

如果需要分表单独存储,建议根据业务的需要预先创建好存放auditLog的表。

注意:如果separeate=true, 记录日志时没有指定repository, 则会记录到表名为default_audit表中。

@Audit(repository = "login")
@RequestMapping("/login")
public String login() {
    return "hello";
}

自定义AuditMetaData

可以修改AuditMetaData.java类来自定义。

MetaData主要是定义Origin和Actor。origin是指操作来源,skeleton中只记录了ip,可以根据需求修改其实现记录IP加域名等等。actor是操作者,skeleton中记录id,userName, realName,实际可以再加上角色,权限等数据。

业务中如何使用

注解方式

@Audit

@Audit注解可以用在方法上,可以用在类上。如果是用在类上,该类中的所有public方法调用都会记录auditLog。

例如:

@Audit
public void foo(Integer bar){
}
** @Audit属性 **** 描述 **** 默认值 **
action自定义action名称Method名称
repository指定auditLog存放的表的前缀。只有separate=true时生效default

@AuditField

@AuditField是指定auditEvent中参数的名称. 不使用@AuditField指定参数名称,记录时默认使用arg1作为参数名称。

例如:

@Audit(repository = "action")
public String foo1(@AuditField(field="stringOne") String string1, @AuditField(field="stringTwo") String string2) {
	}
** @AuditField属性 **** 描述 **
field指定参数的名称

@IgnoreAudit

  1. 在class上使用了@Audit注解,但某些方法不需要审计,可以在该方法上添加@IgnoreAudit方法。

    例如:

   @Audit
   public class UserService {
       @IgnoreAudit
       public void changePassword(String oldPassword, String newPassword) {
           // This method will not be audited.
       }
   }
  1. 指定method的某个参数不被审计。

    例如:

   public class UserService {
       @Audit
       public void login(String username, @IgnoreAudit String password) {
           // password parameter will not be audited.
       }
   }
  1. 忽略审计对象中的成员属性

    例如:

   public class UserService {
       @Audit
       public void saveUser(User user) {
           // password parameter in user object will not be audited.
       }
   }
    
   public class User {
    
       private String username;
       @IgnoreAudit
       private String password;
    
      //Getters and Setters
   }

@DeIdentify

@DeIdentify用于匿名化特定的字段,用*代替。

例如:

@Audit
public void saveCreditCardId(@DeIdentify(left=5) int cardId){}

如果cardId是: 123456789

日志记录会变成: *****6789

** @DeIdentify属性 **** 描述 **
left匿名化左侧字符。例如,@DeIdentify(left=3) -> ***456789
right匿名化右侧字符。例如:@DeIdentify(right=3) -> 123456***
fromLeft从左侧开始匿名化所有字符。例如:@DeIdentify(fromLeft=3) -> 123******
fromRight从右侧开始匿名化所有字符。例如:@DeIdentify(fromRight=3) -> ******789

调用Audit Manager

调用Audit4j提供的audit方法直接记录一条auditEvent;

public void myMethod(String myParam1, Object myParam2) {
     String actor = MyApplicationContext.getAuthanticatedUser();
     AuditManager manager = AuditManager.getInstance();
     manager.audit(new AuditEvent(actor, "myMethod",
                                  new Field("myParam1Name", myParam1),
                                  new Field("myParam2Name", myParam2)));
 }

或者用EventBuilder构造一个AuditEvent

public void myMethod(String myParam1, Object myParam2) {
    String actor = MyApplicationContext.getAuthanticatedUser();
    EventBuilder builder = new EventBuilder();
    builder.addActor(actor).addAction("myMethod")
      .addField("myParam1Name", myParam1)
      .addField("myParam2Name", myParam2);
    AuditManager manager = AuditManager.getInstance();
    manager.audit(builder.build());
 }

注意:AuditManager记录的日志,Audit4j目前都保存到default_table_name设置的表名的表中。(设置不了repository,感觉是个audit4j的bug)

查询AuditLog

AuditLogService.java接口提供了getAuditLogList方法,根据的关键字段进行搜索。

public class AuditQueryDTO extends BaseQueryDTO {
    // 请求者的IP
    private String origin;
    // actor信息
    private String actor;
    // method信息
    private String action;
    // 参数信息
    private String elements;
    // 开始时间
    private Timestamp startTime;
    // 结束时间
    private Timestamp endTime;
}

注意点:

  1. 在controller中使用了BindingResult,需要对该参数加上@IgnoreAudit,不然这条记录可能不会被记录

MORE

  1. Audit4j这个框架目前满足基本记录和查询auditLog的需求。Audit4j也存在一些bug(例如:分表时,@Audit不指定repository时,不会记录到default_table_name设置的默认表名中),和一些局限(例如:不能设置表字段名称,字段类型这些)。
  2. Audit4j开源框架近一年没有更新。有定制化的需求,可以把源码来过了修改。
  3. 目前查询接口返回的elements,仅仅将记录的参数做为 一个字符串返回,可读性的不是那么强;后续可以考虑转成json格式的字符串。
  4. 后续在业务中记录auditLog时,发现有不满足的可以提出来,不断完善。
 类似资料: