配置文件中配置 <plugins> <plugin interceptor="com.audaque.module.safety.support.SqlSecurityAuditInterceptor"> </plugin> </plugins>
package com.audaque.module.safety.support; import java.text.DateFormat; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Properties; import org.apache.ibatis.executor.Executor; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.ParameterMapping; import org.apache.ibatis.mapping.SqlCommandType; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.plugin.Intercepts; import org.apache.ibatis.plugin.Invocation; import org.apache.ibatis.plugin.Plugin; import org.apache.ibatis.plugin.Signature; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.RowBounds; import org.apache.ibatis.type.TypeHandlerRegistry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.util.StringUtils; import com.alibaba.fastjson.JSONObject; import jodd.util.StringUtil; @Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }), @Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class }) }) public class SqlSecurityAuditInterceptor implements Interceptor { private static final Logger logger = LoggerFactory.getLogger(SqlSecurityAuditInterceptor.class); private static String dataSourceName = ""; @Override public Object intercept(Invocation invocation) throws Throwable { String bSql = null; try { if (SpringContextUtils.getApplicationContext() == null) { return invocation.proceed(); } Object o = SpringContextUtils.getBean("securityAuditServiceImpl"); if (o == null) { return invocation.proceed(); } Object[] args = invocation.getArgs(); MappedStatement mappedStatement = (MappedStatement) args[0]; Object param = null; if (args.length > 1) { param = args[1]; } // 数据源url String dataSourceName = getDataSourceName(); BoundSql boundSql = mappedStatement.getBoundSql(param); bSql = boundSql.getSql(); if (bSql.length() < 1000) { // sql String sql = showSql(mappedStatement.getConfiguration(), boundSql); SqlParser parser = new MysqlParser(); // 表名 List<String> tableNames = parser.getTables(bSql); // 操作字段名 Map<String, List<String>> columns = parser.getColumns(bSql); // 用户ID Integer userId = -1; String userName = "-"; try { userId = SecurityContext.getUserId(); // 用户名 if (userId == null) { userId = -1; userName = "-"; } else { userName = SecurityContext.getUserName(); } } catch (Exception e) { logger.debug("未找到登陆用户"); } // 时间 Date now = new Date(); // 操作类型 SqlCommandType commandType = mappedStatement.getSqlCommandType(); SecurityAudit sa = new SecurityAudit(); sa.setDataSourceName(dataSourceName); sa.setTableName(JSONObject.toJSONString(tableNames)); sa.setColumnName(JSONObject.toJSONString(columns)); sa.setOptTime(now); sa.setOptType(commandType.name()); sa.setUserId(userId); sa.setUserName(userName); int optLevel = commandType.ordinal(); if (optLevel == 2) { optLevel = 3; } sa.setOptLevel(optLevel); sa.setOptSql(sql); SecurityAuditService securityAuditService = (SecurityAuditServiceImpl) o; securityAuditService.insert(sa); } } catch (Exception e) { logger.error("记录安全审计日志失败,sql:" + bSql, e); } return invocation.proceed(); } private static String getDataSourceName() { if (StringUtils.isEmpty(dataSourceName)) { DruidDataSource ds = (DruidDataSource) SpringContextUtils.getBean(DruidDataSource.class); String url = ds.getUrl(); int startIndex = url.indexOf("//"); int endIndex = url.indexOf("?"); if (StringUtil.isNotEmpty(url)) { if (endIndex > -1) { dataSourceName = url.substring(startIndex + 1, endIndex); } else { dataSourceName = url.substring(startIndex + 1); } } } return dataSourceName; } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { } public String showSql(Configuration configuration, BoundSql boundSql) { Object parameterObject = boundSql.getParameterObject(); List<ParameterMapping> parameterMappings = boundSql.getParameterMappings(); String sql = boundSql.getSql().replaceAll("[\\s]+", " "); if (parameterMappings.size() > 0 && parameterObject != null) { TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry(); if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) { sql = sql.replaceFirst("\\?", getParameterValue(parameterObject)); } else { MetaObject metaObject = configuration.newMetaObject(parameterObject); for (ParameterMapping parameterMapping : parameterMappings) { String propertyName = parameterMapping.getProperty(); if (metaObject.hasGetter(propertyName)) { Object obj = metaObject.getValue(propertyName); String parameterValue = getParameterValue(obj); // 添加对特殊字符的处理 parameterValue = java.util.regex.Matcher.quoteReplacement(parameterValue); sql = sql.replaceFirst("\\?", parameterValue); } else if (boundSql.hasAdditionalParameter(propertyName)) { Object obj = boundSql.getAdditionalParameter(propertyName); sql = sql.replaceFirst("\\?", getParameterValue(obj)); } } } } return sql; } private String getParameterValue(Object obj) { String value = null; if (obj instanceof String) { value = "'" + obj.toString() + "'"; } else if (obj instanceof Date) { DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA); value = "'" + formatter.format(obj) + "'"; // System.out.println(value); } else { if (obj != null) { value = obj.toString(); } else { value = ""; } } return value; } }