Explorar el Código

第三方接口添加日志

gao.qiang hace 1 año
padre
commit
e0a93e4e75

+ 41 - 0
base-common/src/main/java/com/ozs/common/annotation/SdkLog.java

@@ -0,0 +1,41 @@
+package com.ozs.common.annotation;
+
+import com.ozs.common.enums.BusinessTypeSdk;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 第三方自定义操作日志记录注解
+ *
+ * @author hx
+ */
+@Target({ ElementType.PARAMETER, ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface SdkLog
+{
+    /**
+     * 模块
+     */
+    public String title() default "";
+
+    /**
+     * 功能
+     */
+    public BusinessTypeSdk businessType() default BusinessTypeSdk.OTHER;
+    
+
+    /**
+     * 是否保存请求的参数
+     */
+    public boolean isSaveRequestData() default true;
+
+    /**
+     * 是否保存响应的参数
+     */
+    public boolean isSaveResponseData() default true;
+}

+ 52 - 0
base-common/src/main/java/com/ozs/common/core/domain/entity/SvcAddress.java

@@ -0,0 +1,52 @@
+package com.ozs.common.core.domain.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import io.swagger.annotations.ApiModel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ *报警消息访问令牌参数验证表
+ * </p>
+ *
+ * @author ozs
+ * @since 2023-02-28
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ApiModel("报警消息访问令牌参数验证表")
+public class SvcAddress implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 授权类型,客户端模式(client_credentials)
+     */
+    private String grantType;
+
+    /**
+     * 主键
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 客户端编号
+     */
+    private String clientId;
+
+    /**
+     * 客户端密钥
+     */
+    private String clientSecret;
+
+
+}

+ 127 - 0
base-common/src/main/java/com/ozs/common/core/domain/entity/SysOperLog.java

@@ -0,0 +1,127 @@
+package com.ozs.common.core.domain.entity;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ozs.common.annotation.Excel;
+import com.ozs.common.annotation.Excel.ColumnType;
+import com.ozs.common.core.domain.BaseEntityExp;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+/**
+ * 操作日志记录表 oper_log
+ *
+ * @author hx
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class SysOperLog extends BaseEntityExp {
+
+    /**
+     * 日志主键
+     */
+    @Excel(name = "操作序号", cellType = ColumnType.NUMERIC)
+    private Long operId;
+
+    /**
+     * 操作模块
+     */
+    @Excel(name = "操作模块")
+    private String title;
+
+    /**
+     * 业务类型(0其它 1新增 2修改 3删除)
+     */
+    @Excel(name = "业务类型", readConverterExp = "0=其它,1=新增,2=修改,3=删除,4=授权,5=导出,6=导入,7=强退,8=生成代码,9=清空数据")
+    private Integer businessType;
+
+    /**
+     * 业务类型数组
+     */
+   // private Integer[] businessTypes;
+
+    /**
+     * 请求方法
+     */
+    @Excel(name = "请求方法")
+    private String method;
+
+    /**
+     * 请求方式
+     */
+    @Excel(name = "请求方式")
+    private String requestMethod;
+
+    /**
+     * 操作类别(0其它 1后台用户 2手机端用户)
+     */
+    //@Excel(name = "操作类别", readConverterExp = "0=其它,1=后台用户,2=手机端用户")
+    private Integer operatorType;
+
+    /**
+     * 操作人员
+     */
+    @Excel(name = "操作人员")
+    private String userId;
+
+    /**
+     * 部门名称
+     */
+    @Excel(name = "部门名称")
+    private String deptName;
+
+    /**
+     * 请求url
+     */
+    @Excel(name = "请求地址")
+    private String operUrl;
+
+    /**
+     * 操作地址
+     */
+    @Excel(name = "操作地址")
+    private String operIp;
+
+    /**
+     * 操作地点
+     */
+    @Excel(name = "操作地点")
+    private String operLocation;
+
+    /**
+     * 请求参数
+     */
+    @Excel(name = "请求参数")
+    private String operParam;
+
+    /**
+     * 返回参数
+     */
+    @Excel(name = "返回参数")
+    private String jsonResult;
+
+    /**
+     * 操作状态(0正常 1异常)
+     */
+    @Excel(name = "状态", readConverterExp = "1=正常,2=异常")
+    private Integer status;
+
+    /**
+     * 错误消息
+     */
+    //@Excel(name = "错误消息")
+    private String errorMsg;
+
+    /**
+     * 操作时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "操作时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private Date operTime;
+
+}

+ 29 - 0
base-common/src/main/java/com/ozs/common/enums/BusinessTypeSdk.java

@@ -0,0 +1,29 @@
+package com.ozs.common.enums;
+
+/**
+ * 第三方业务操作类型
+ *
+ * @author hx
+ */
+public enum BusinessTypeSdk
+{
+    /**
+     * 获取访问令牌
+     */
+    TOKEN,
+
+    /**
+     * 报警信息数据传输
+     */
+    ALARM,
+
+    /**
+     * 设备状态数据传输
+     */
+    STATE,
+
+    /**
+     * 其它
+     */
+    OTHER,
+}

+ 223 - 0
base-common/src/main/java/com/ozs/common/utils/LogAspectSDK.java

@@ -0,0 +1,223 @@
+package com.ozs.common.utils;
+
+import com.alibaba.fastjson2.JSON;
+import com.ozs.common.annotation.SdkLog;
+import com.ozs.common.constant.Constants;
+import com.ozs.common.core.domain.entity.SvcAddress;
+import com.ozs.common.core.domain.entity.SysOperLog;
+import com.ozs.common.enums.HttpMethod;
+import com.ozs.common.filter.PropertyPreExcludeFilter;
+import com.ozs.common.utils.ip.IpUtils;
+import com.ozs.common.utils.stateSecrets.SM4Utils;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.AfterReturning;
+import org.aspectj.lang.annotation.AfterThrowing;
+import org.aspectj.lang.annotation.Aspect;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * 操作日志记录处理
+ *
+ * @author hx
+ */
+@Aspect
+@Component
+public class LogAspectSDK {
+
+    @Resource
+    private ApiTokenUtils apiTokenUtils;
+    /**
+     * 排除敏感属性字段
+     */
+    public static final String[] EXCLUDE_PROPERTIES = {"password", "oldPassword", "newPassword", "confirmPassword"};
+    private static final Logger log = LoggerFactory.getLogger(LogAspectSDK.class);
+
+    /**
+     * 处理完请求后执行
+     *
+     * @param joinPoint 切点
+     */
+    @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")
+    public void doAfterReturning(JoinPoint joinPoint, SdkLog controllerLog, Object jsonResult) {
+        handleLog(joinPoint, controllerLog, null, jsonResult);
+    }
+
+    /**
+     * 拦截异常操作
+     *
+     * @param joinPoint 切点
+     * @param e         异常
+     */
+    @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")
+    public void doAfterThrowing(JoinPoint joinPoint, SdkLog controllerLog, Exception e) {
+        handleLog(joinPoint, controllerLog, e, null);
+    }
+
+    protected void handleLog(final JoinPoint joinPoint, SdkLog controllerLog, final Exception e, Object jsonResult) {
+        try {
+            RequestAttributes ra = RequestContextHolder.getRequestAttributes();
+            ServletRequestAttributes sra = (ServletRequestAttributes) ra;
+            assert sra != null;
+            HttpServletRequest request = sra.getRequest();
+            
+            // 获取当前的用户
+            String token = apiTokenUtils.getGeoHazardMonitorToken(request);
+
+            // *========数据库日志=========*//
+            SysOperLog operLog = new SysOperLog();
+            operLog.setStatus(Integer.valueOf(Constants.SUCCESS));
+            // 请求的地址
+            String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
+            operLog.setOperIp(ip);
+            operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));
+            if (token != null) {
+                String[] split = token.split("-");
+                operLog.setUserId(split[split.length-2]);
+            }
+
+            if (e != null) {
+                operLog.setStatus(Integer.valueOf(Constants.FAIL));
+                operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
+            }
+            // 设置方法名称
+            String className = joinPoint.getTarget().getClass().getName();
+            String methodName = joinPoint.getSignature().getName();
+            operLog.setMethod(className + "." + methodName + "()");
+            // 设置请求方式
+            operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
+            // 处理设置注解上的参数
+            getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);
+            log.info("接口打印日志======="+operLog);
+        } catch (Exception exp) {
+            // 记录本地异常日志
+            log.error("异常信息:{}", exp.getMessage());
+            exp.printStackTrace();
+        }
+    }
+
+    /**
+     * 获取注解中对方法的描述信息 用于Controller层注解
+     *
+     * @param log     日志
+     * @param operLog 操作日志
+     * @throws Exception
+     */
+    public void getControllerMethodDescription(JoinPoint joinPoint, SdkLog log, SysOperLog operLog, Object jsonResult) throws Exception {
+        // 设置action动作
+        operLog.setBusinessType(log.businessType().ordinal());
+        // 设置标题
+        operLog.setTitle(log.title());
+        // 是否需要保存request,参数和值
+        if (log.isSaveRequestData()) {
+            // 获取参数的信息,传入到数据库中。
+            setRequestValue(joinPoint, operLog);
+        }
+        // 是否需要保存response,参数和值
+        if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult)) {
+            operLog.setJsonResult(SM4Utils.decryptData_ECB(StringUtils.substring(JSON.toJSONString(jsonResult), 0, 2000),"4370780c9a8c43e5"));
+        }
+    }
+
+    /**
+     * 获取请求的参数,放到log中
+     *
+     * @param operLog 操作日志
+     * @throws Exception 异常
+     */
+    private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog) throws Exception {
+        String requestMethod = operLog.getRequestMethod();
+        if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) {
+            String params = argsArrayToString(joinPoint.getArgs());
+            if ("/token".equals(operLog.getOperUrl())){
+                operLog.setOperParam(StringUtils.substring(params, 0, 2000));
+                Object[] args = joinPoint.getArgs();
+                String arg = String.valueOf(args[0]);
+                String[] split = arg.split(",");
+                String id=split[split.length-2];
+                String[] split1 = id.split("=");
+                operLog.setUserId(split1[1]);
+            }else {
+                operLog.setOperParam(SM4Utils.decryptData_ECB(StringUtils.substring(params, 0, 2000), "4370780c9a8c43e5"));
+            }
+        } else {
+            Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
+            if ("/token".equals(operLog.getOperUrl())) {
+                StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter()), 0, 2000);
+                Object[] args = joinPoint.getArgs();
+                String arg = String.valueOf(args[0]);
+                String[] split = arg.split(",");
+                String id=split[split.length-2];
+                String[] split1 = id.split("=");
+                operLog.setUserId(split1[1]);
+            } else {
+                operLog.setOperParam(SM4Utils.decryptData_ECB(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter()), 0, 2000), "4370780c9a8c43e5"));
+            }
+        }
+    }
+
+    /**
+     * 参数拼装
+     */
+    private String argsArrayToString(Object[] paramsArray) {
+        String params = "";
+        if (paramsArray != null && paramsArray.length > 0) {
+            for (Object o : paramsArray) {
+                if (StringUtils.isNotNull(o) && !isFilterObject(o)) {
+                    try {
+                        String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter());
+                        params += jsonObj.toString() + " ";
+                    } catch (Exception e) {
+                    }
+                }
+            }
+        }
+        return params.trim();
+    }
+
+    /**
+     * 忽略敏感属性
+     */
+    public PropertyPreExcludeFilter excludePropertyPreFilter() {
+        return new PropertyPreExcludeFilter().addExcludes(EXCLUDE_PROPERTIES);
+    }
+
+    /**
+     * 判断是否需要过滤的对象。
+     *
+     * @param o 对象信息。
+     * @return 如果是需要过滤的对象,则返回true;否则返回false。
+     */
+    @SuppressWarnings("rawtypes")
+    public boolean isFilterObject(final Object o) {
+        Class<?> clazz = o.getClass();
+        if (clazz.isArray()) {
+            return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
+        } else if (Collection.class.isAssignableFrom(clazz)) {
+            Collection collection = (Collection) o;
+            for (Object value : collection) {
+                return value instanceof MultipartFile;
+            }
+        } else if (Map.class.isAssignableFrom(clazz)) {
+            Map map = (Map) o;
+            for (Object value : map.entrySet()) {
+                Map.Entry entry = (Map.Entry) value;
+                return entry.getValue() instanceof MultipartFile;
+            }
+        }
+        return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
+                || o instanceof BindingResult;
+    }
+}