【模式一】4.sql审计-每次执行的sql语句及参数信息保存到日志记录表

使用的是mybatis-flex官网自带的sql审计功能
首先展示下 记录日志的表及实体类

/**
 * 所有的sql操作记录 实体类。
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class LogSqlAudit implements Serializable {

    /**
     * 编号
     */
    @Id(keyType = KeyType.Auto)
    private Long id;

    /**
     * sql语句
     */
    private String sqlText;

    /**
     * 访问人
     */
    private String userId;

    /**
     * 访问IP
     */
    private String userIp;

    /**
     * 耗时
     */
    private Long exeTime;

    /**
     * 访问地址
     */
    private String url;

    /**
     * 执行时间
     */
    private Date createDate;

}

在这里插入图片描述
测试的接口

@RestController
@RequiredArgsConstructor
@RequestMapping("log")
public class LogController {

    private final LogSqlAuditService logSqlAuditService;
    private final LogSqlErrorService logSqlErrorService;

    @PostMapping("savaLog")
    public BaseResponse<LogSqlAudit> save(@RequestBody LogSqlAudit logSqlAudit){
        boolean save = logSqlAuditService.save(logSqlAudit);
        if(!save){
            return ResultUtils.error(ErrorCode.NULL_ERROR);
        }
        return ResultUtils.success(logSqlAudit);
    }

    @PostMapping("getLogFx")
    public BaseResponse<List<LogSqlError>> getLog(){
        List<LogSqlError> list = logSqlErrorService.list();
        return ResultUtils.success(list);
    }
}

拦截器中配置放行的接口,让这个接口可以随便访问次数。不会触发禁用该用户访问接口限流的限制。无限访问。

在这里插入图片描述
以上改完,接下来才是正题。
MyMessageFactory 每次访问接口就会进来执行代码


@Component
@RequiredArgsConstructor
public class MyMessageFactory implements MessageFactory {
    //private final RegUtil regUtil;//目前先注释,之后加入获取用户信息方法在放开
    private final HttpServletRequest request;
    @Override
    public AuditMessage create() {
        AuditMessage message = new AuditMessage();
        // 在这里
        // 设置 message 的基础内容,包括 platform、module、url、user、userIp、hostIp 内容
        // 剩下的 query、queryParams、queryCount、queryTime、elapsedTime 为 mybatis-flex 设置
        message.setPlatform("IPRMIS2.0");
        message.setUser("admin");//暂时写固定 之后有jwt或者redis存登录人的时候,再去改
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if("0:0:0:0:0:0:0:1".equals(ip)){//本地运行会出现这个情况,如果部署到公网上就不会是0:0:0:0:0:0:0:1 会显示本机公网的ip 这里就是本地电脑先写本地
            ip = "127.0.0.1";
        }
        message.setUserIp(ip);
        message.setUrl(request.getRequestURI());
        return message;
    }
}

MyMessageReporter 记录一段时间的接口才会触发sendMessages

@Slf4j
@Component
public class MyMessageReporter implements MessageReporter {

    @Override
    public void sendMessages(List<AuditMessage> messages) {

        messages.forEach(m -> {
            System.out.println(">>>>>>Sql Audit: " + m.toString());
            if(m.getQuery().contains("log_sql_audit")){//这是记录日志的表 这里就不用存日志记录表了,排除
                return;
            }
            try {
                //1, 得到URL对象
                URL url = new URL("http://10.11.6.88:9001/log/savaLog");
                //2, 打开连接
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                //3, 设置提交类型
                conn.setRequestMethod("POST");
                conn.setRequestProperty("content-Type", "application/json; charset=utf-8");
                //4, 设置允许写出数据,默认是不允许 false
                conn.setDoOutput(true);
                conn.setDoInput(true);//当前的连接可以从服务器读取内容, 默认是true
                //5, 获取向服务器写出数据的流
                OutputStream os = conn.getOutputStream();
                String sqlText = m.getQuery();
                LogSqlAudit logSqlAudit = new LogSqlAudit();
                logSqlAudit.setSqlText(sqlText);
                logSqlAudit.setCreateDate(new Date());
                logSqlAudit.setUrl(m.getUrl());
                logSqlAudit.setExeTime(m.getElapsedTime());
                String ip = m.getUserIp();
                if ("0:0:0:0:0:0:0:1".equals(ip)) {//本地运行会出现这个情况,如果部署到公网上就不会是0:0:0:0:0:0:0:1 会显示本机公网的ip 这里就是本地电脑先写本地
                    ip = "127.0.0.1";
                }
                logSqlAudit.setUserIp(ip);
                logSqlAudit.setUserId(m.getUser());
                ObjectMapper objectMapper = new ObjectMapper();
                String jsonlog = objectMapper.writeValueAsString(logSqlAudit);//实体类转成json
                //参数是键值队  , 不以"?"开始
                os.write(jsonlog.getBytes());
                os.flush();
                //6, 获取响应的数据
                //得到服务器写回的响应数据
                BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
                String str = br.readLine();
                JSONObject json = JSONObject.parseObject(str);

                System.out.println("响应内容为:  " + json);
            }catch(Exception e){
                throw new BusinessException("sql审计存入数据失败",500,"");
            }

        });


    }



}

MyAuditConfiguration配置

@Configuration
@RequiredArgsConstructor
public class MyAuditConfiguration implements MyBatisFlexCustomizer {

    private final MyMessageFactory myMessageFactory;

    @SneakyThrows
    @Override
    public void customize(FlexGlobalConfig flexGlobalConfig) {
        // 开启 SQL 审计
        AuditManager.setAuditEnable(true);
        //设置
        AuditManager.setMessageFactory(myMessageFactory);
        AuditManager.setMessageReporter(new MyMessageReporter());

    }
}

然后调用任意接口,看一下效果吧
在这里插入图片描述
在这里插入图片描述
成功记录!

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值