需求:audit log,针对30多个接口,需要对操作者的行为做一定对记录
实现:
注解的定义
1.使用了两种元注解,很基础,作为使用过的人,应该要知道不仅只有这两种,也不仅只是这些参数
2.type是用于业务,后面则是很简单的参数,type总共有三种,分别对应了三种场景,auditlog,securityLog,invalid message
题外话—这也是金融系统的一个特点,安全性要求高,不仅仅是基本的权限控制,服务器上云,数据库备份,容灾,
甚至在任何一次操作都会在系统中留下记录
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Log {
LogConstant.TypeEnum[] type();
LogConstant.ModuleEnum module();
LogConstant.ActionTypeEnum actionType();
}
环绕增强
一、环绕增强的基本实现
核心注解@Aspect,@Around,pjp就是切入点pjp.process之前就是前置增强,try,就是异常抛出增强
主意这里的url和ip的获取,url比较简单,ip则因为nginx,需要一点解析
二、kafka发送的业务
消息的发送有一些封装,以及多线程多使用,具体
就logService.sendAuditLog(auditLogCreateParam);还需要做分析
@Aspect
@Component
@Slf4j
@Deprecated
public class LogAspectHandler {
@Autowired
private LogService logService;
@Around(value = "@annotation(logAnnotation)")
public Object intercept(ProceedingJoinPoint proceedingJoinPoint, Log logAnnotation) throws Throwable {
Object result;
Map<String, Object> paramMap = new HashMap<>();
Object[] args = proceedingJoinPoint.getArgs();
for (Object arg : args) {
if (arg instanceof HttpServletRequest) {
paramMap.put("url", ((HttpServletRequest) arg).getServletPath());
paramMap.put("clientIp", IpAddressUtil.getIpAdrress((HttpServletRequest) arg));
// paramMap.put("userId", CookieUtil.getUsername(((HttpServletRequest) arg)));
break;
}
}
MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
final Annotation[][] annotationsArray = signature.getMethod().getParameterAnnotations();
for (int i = 0; i < annotationsArray.length; i++) {
for (Annotation a: annotationsArray[i]) {
if (a instanceof RequestBody) {
paramMap.put("detail", JsonUtil.toJson(proceedingJoinPoint.getArgs()[i]));
}
}
}
List<LogConstant.TypeEnum> logType = Arrays.asList(logAnnotation.type());
if (logType.contains(LogConstant.TypeEnum.AUDIT_LOG)) {
AuditLogCreateParam auditLogCreateParam = new AuditLogCreateParam();
auditLogCreateParam.setActionType(logAnnotation.actionType().getValue());
auditLogCreateParam.setModule(logAnnotation.module().getValue());
auditLogCreateParam.setOperationTime(LocalDateTime.now());
BeanUtils.populate(auditLogCreateParam, paramMap);
logService.sendAuditLog(auditLogCreateParam);
}
if (logType.contains(LogConstant.TypeEnum.SECURITY_LOG)) {
SecurityLogCreateParam securityLogCreateParam = new SecurityLogCreateParam();
securityLogCreateParam.setActionType(logAnnotation.actionType().toString());
securityLogCreateParam.setModule(logAnnotation.module().getValue());
securityLogCreateParam.setOperationTime(LocalDateTime.now());
BeanUtils.populate(securityLogCreateParam, paramMap);
logService.sendSecurityLog(securityLogCreateParam);
}
try {
result = proceedingJoinPoint.proceed();
} catch (Throwable e) {
log.error("LogAspectHandler-Interceptor",e);
throw e;
}
return result;
}
}
获取ip
/**
* 获取Ip地址
* @param request
* @return
*/
public static String getIpAdrress(HttpServletRequest request) {
String Xip = request.getHeader("X-Real-IP");
String XFor = request.getHeader("X-Forwarded-For");
if(StringUtils.isNotEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)){
//多次反向代理后会有多个ip值,第一个ip才是真实ip
int index = XFor.indexOf(",");
if(index != -1){
return XFor.substring(0,index);
}else{
return XFor;
}
}
XFor = Xip;
if(StringUtils.isNotEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)){
return XFor;
}
if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
XFor = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
XFor = request.getHeader("WL-Proxy-Client-IP");
}
if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
XFor = request.getHeader("HTTP_CLIENT_IP");
}
if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
XFor = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
XFor = request.getRemoteAddr();
}
return XFor;
}
来源:CSDN
作者:竹鼠三元一只
链接:https://blog.csdn.net/weixin_43343786/article/details/104330734