首页 > 基础资料 博客日记

【JAVA】JAVA系统日志设计与实现

2025-01-13 23:30:10基础资料围观109

文章【JAVA】JAVA系统日志设计与实现分享给大家,欢迎收藏Java资料网,专注分享技术知识

一、在做系统的时候,特别是后台管理系统的时候,需要记录每一个管理员对系统的操作行为,这是合规的要求,也是方便业务出现错误操作,排查到错误的操作和相关人员。那么对于JAVA系统来说怎么手机到系统的操作日志呢。

系统日志合规要求:

系统操作日志的合规要求‌主要包括以下几个方面:

  1. 日志记录的重要性‌:日志记录能够记录系统的运行状态、用户操作、异常情况等信息,通过对日志的审计和分析,及时发现系统中存在的问题,加强对系统安全性的保护,便于系统运维和故障排查‌1。

  2. 合规要求‌:根据《网络安全法》等相关法律法规,各类网络运营者都有义务建立健全的操作日志记录制度,对系统的关键操作和安全事件进行记录和保留。因此,设计合规的操作日志记录方案对于保障系统安全、符合法规具有重要意义‌1。

  3. 日志内容规范‌:操作日志应当包含操作的具体内容、操作人员信息、操作时间、操作结果以及异常情况等内容,以便于对操作过程进行全面的追溯和分析。同时,需要规范各类日志记录的格式和内容,确保日志的有效性和可读性‌1。

  4. 安全性要求‌:在设计操作日志方案时,需要考虑日志记录的安全性,避免日志被恶意篡改或删除。可以采用加密、权限控制等手段保护日志的完整性,同时对日志进行定期备份,防止意外数据丢失‌1。

  5. 存储和备份‌:原始日志应在产生日志设备上保存一定时间(如14天),在磁盘空间不足的情况下,系统管理员应根据日志生成时间的先后删除较早的日志。同时,系统管理员需要将原始日志收集到日志统一存储系统进行集中管理‌2。

  6. 合规性设计‌:设计一个符合合规要求的日志系统时,应考虑以下几点:

    • 日志内容‌:只记录必要的信息,避免记录敏感数据。
    • 日志级别‌:使用合适的日志级别(如INFO, WARNING, ERROR),避免记录过多的调试信息。
    • 日志存储‌:确保日志存储在安全的地方,采取适当的加密措施。
    • 日志保留期限‌:设定合理的日志保留期限,并定期清理过期日志。
    • 访问控制‌:确保只有授权用户才能访问日志文件,可以使用文件权限和访问控制列表(ACL)来限制访问。
    • 加密‌:对敏感日志进行加密存储,使用强加密算法如AES。
    • 定期审计和审查‌:定期审计日志文件,确保没有未经授权的访问或异常活动。
    • 监控和警报‌:设置监控系统实时监控日志文件的变化,并在检测到异常活动时发送警报。
    • 数据脱敏‌:在记录日志时,对敏感数据进行脱敏处理,例如隐藏部分信用卡号、社会安全号码等‌3。

 

二、下面是具体实现

首先所有的操作都是有一个个controller产生的,增删查改,入参,出参无非这就几个。只是我们想的是如何统一对数据进行收集和处理,而不是将日志收集放在每个controller里面。

1、首先我们要建一个表用来存储日志,这里暂且命名为:base_sys_operate_log

CREATE TABLE `base_sys_operate_log` (
  `id` int NOT NULL AUTO_INCREMENT,
  `role_type` int DEFAULT NULL,
  `operator_id` int DEFAULT NULL,
  `operator_name` varchar(255) DEFAULT NULL,
  `package_name` varchar(255) DEFAULT NULL,
  `module_name` varchar(255) DEFAULT NULL,
  `action_name` varchar(255) DEFAULT NULL,
  `func_id` int DEFAULT NULL,
  `action_vo_type` varchar(255) DEFAULT NULL,
  `action_vo_id` int DEFAULT NULL,
  `action_vo_params` varchar(2000) DEFAULT NULL,
  `exception` varchar(2000) DEFAULT NULL,
  `status_code` int DEFAULT NULL,
  `error_info` varchar(255) DEFAULT NULL,
  `operat_name` varchar(1000) DEFAULT NULL,
  `info` varchar(1000) DEFAULT NULL COMMENT '越权信息',
  `remote_addr` varchar(128) DEFAULT NULL,
  `user_name` varchar(256) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `server_ip` varchar(1000) DEFAULT NULL,
  `page_name` varchar(255) DEFAULT NULL COMMENT '页面名称',
  `page_url` varchar(255) DEFAULT NULL COMMENT '页面路由',
  PRIMARY KEY (`id`),
  KEY `create_time_index` (`create_time`),
  KEY `operat_name_index` (`operat_name`(255)),
  KEY `user_name_index` (`user_name`(255))
) ENGINE=InnoDB AUTO_INCREMENT=6424418 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC

2、那就是实体类的编写

public class OperateLog {
	private Integer operatorId;    //操作员ID
	private String operatorName;   //操作员名称
	private Date createTime;        //创建时间
	private String packageName;		//包名
	private String moduleName;		//模块名
	private String actionName;		//action名称
	private Integer funcId;			//功能id
	private Integer roleType;       //角色类型
	private String actionVoType;	//actionVo类型
	private Long actionVoId;		//actionVoid
	private String actionVoParams;	//actionVo参数
	private String exception;		//异常
	private String errorInfo;		//异常信息
	private Integer statusCode;		//状态码 0成功 其他失败
	private String operatName;
	private String info;			// 日志信息
	private String remoteAddr;//客户端IP   remoteAddr
	private Integer count;
	private Date dateFormat;
	private String userName;
	private String serverIp;
	/**
	 * 页面名称
	 */
	private String pageName;
	/**
	 * 页面地址
	 */
	private String pageUrl;

	public final static Integer LOG_SYS_LOG=1;
	public final static Integer LOG_BIZ_LOG=4;
	
	public Integer getOperatorId() {
		return operatorId;
	}
	public void setOperatorId(Integer operatorId) {
		this.operatorId = operatorId;
	}
	public String getOperatorName() {
		return operatorName;
	}
	public void setOperatorName(String operatorName) {
		this.operatorName = operatorName;
	}
	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
	public Date getCreateTime() {
		return createTime;
	}
	public void setCreateTime(Date createTime) {
		this.createTime = createTime;
	}
	public String getPackageName() {
		return packageName;
	}
	public void setPackageName(String packageName) {
		this.packageName = packageName;
	}
	public String getPackageNameStr() {
		if("system".equals(packageName)){
			return packageName = "服务平台";
		}else if("merchant".equals(packageName)){
			return packageName = "商户平台";
		}
		return packageName;
	}
	public String getModuleName() {
		return moduleName;
	}
	public void setModuleName(String moduleName) {
		this.moduleName = moduleName;
	}
	public String getActionName() {
		return actionName;
	}
	public void setActionName(String actionName) {
		this.actionName = actionName;
	}
	public Integer getFuncId() {
		return funcId;
	}
	public void setFuncId(Integer funcId) {
		this.funcId = funcId;
	}
	public String getActionVoType() {
		return actionVoType;
	}
	public void setActionVoType(String actionVoType) {
		this.actionVoType = actionVoType;
	}
	public Long getActionVoId() {
		return actionVoId;
	}
	public void setActionVoId(Long actionVoId) {
		this.actionVoId = actionVoId;
	}
	public String getActionVoParams() {
		return actionVoParams;
	}
	public void setActionVoParams(String actionVoParams) {
		this.actionVoParams = actionVoParams;
	}
	public String getException() {
		return exception;
	}
	public void setException(String exception) {
		this.exception = exception;
	}
	public Integer getStatusCode() {
		return statusCode;
	}
	public String getStatusCodeStr() {
		return "";//Dict.getDict("SYS_EXCEPTION").getValueByKeyInt(statusCode);
	}
	public String getStatusCodeResult() {
		if(statusCode==null||statusCode== 0){
			return "成功";
		}else{
			return "失败";
		}
	}
	public void setStatusCode(Integer statusCode) {
		this.statusCode = statusCode;
	}
	public String getOperatName() {
		return operatName;
	}
	public void setOperatName(String operatName) {
		this.operatName = operatName;
	}
	public String getInfo() {
		return info;
	}
	public void setInfo(String info) {
		this.info = info;
	}
	public void setLogNameInfo(String operatName,String info) {
		this.operatName = operatName;
		this.info = info;
	}
	public void setLogNameInfo(String operatName,String info, Integer roleType) {
		this.operatName = operatName;
		this.info = info;
		this.roleType=roleType;
	}
	public String getRemoteAddr() {
		return remoteAddr;
	}
	public void setRemoteAddr(String remoteAddr) {
		this.remoteAddr = remoteAddr;
	}
	
	public Integer getRoleType() {
		return roleType;
	}
	public void setRoleType(Integer roleType) {
		this.roleType = roleType;
	}
	public String getRoleTypeStr() {
		if(roleType == null)
			return "其他";
		if(roleType ==4){
			return "业务日志";
		}else{
			return "系统日志";
		}
	}
	public Integer getCount() {
		return count;
	}
	public void setCount(Integer count) {
		this.count = count;
	}
	public String getErrorInfo() {
		return errorInfo;
	}
	public void setErrorInfo(String errorInfo) {
		this.errorInfo = errorInfo;
	}

	@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
	public Date getDateFormat() {
		return dateFormat;
	}
	public void setDateFormat(Date dateFormat) {
		this.dateFormat = dateFormat;
	}
	
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getServerIp() {
		return serverIp;
	}
	public void setServerIp(String serverIp) {
		this.serverIp = serverIp;
	}

	public String getPageName() {
		return pageName;
	}

	public void setPageName(String pageName) {
		this.pageName = pageName;
	}

	public String getPageUrl() {
		return pageUrl;
	}

	public void setPageUrl(String pageUrl) {
		this.pageUrl = pageUrl;
	}
}

抽象Controller类进行统一处理

    public static void recordlog(String packageName, String nameSpace, String actionName, HttpServletRequest request,
                                 HttpServletResponse response, BaseAction action, ResponseVo responseVo) {
        try {
            recordLogRun(packageName, nameSpace, actionName, request, response, action, responseVo);
        } catch (Exception e) {
            logger.error("记录操作日志异常:", e);
        }
    }

    public static void recordLogRun(String packageName, String nameSpace, String actionName,
                                    HttpServletRequest request, HttpServletResponse response, BaseAction action,
                                    ResponseVo responseVo) {
        if (actionName.startsWith("get") || actionName.startsWith("query") || actionName.startsWith("load") || (!packageName.equals("system") && !packageName.equals("merchant") && !packageName.equals("enterprise"))) {
        } else if (action.getCommonException() != null && action.getCommonException().getErrorCode() == 1000) {

        } else {
            OperateLog operateLog = new OperateLog();
            Func func = new Func();
            operateLog.setPackageName(packageName);
            operateLog.setModuleName(nameSpace);
            BaseCustomer customer = null;
            try {
                customer = action.getLoginCustomer();
            } catch (Exception e) {

            }
            if (customer != null) {
                if (customer instanceof Operator) {
                    Operator o = (Operator) customer;
                    operateLog.setOperatorName(o.getRealName());
                    operateLog.setOperatorId(o.getId());
                    operateLog.setUserName(o.getUserName());
                } else if (customer instanceof AppThirdAuth) {
                    AppThirdAuth a = (AppThirdAuth) customer;
                    operateLog.setOperatorName(a.getAppNo());
                    operateLog.setOperatorId(a.getId());
                    operateLog.setUserName(a.getAppName());
                }
            }
            String referer = "";
            String servletPath = request.getServletPath();
            if (servletPath != null) {
                referer = servletPath;
            }
            if (action.getResultType() != null && action.getResultType().equals("json")) {
                referer = request.getHeader("Referer");
            }
            if (StringUtils.isNotBlank(referer)) {
                if (servletPath.contains("/login/login")) {// 系统退出日志
                    operateLog.setOperatName("登录系统");
                    operateLog.setRoleType(OperateLog.LOG_SYS_LOG);// 从 func中获取roleType
                } else if (servletPath.contains("/login/logout")) {// 系统退出日志
                    operateLog.setOperatName("退出系统");
                    operateLog.setRoleType(OperateLog.LOG_SYS_LOG);// 从 func中获取roleType /home/home
                } else if (servletPath.contains("/home/home")) {// 系统退出日志
                    operateLog.setOperatName("系统home");
                    operateLog.setRoleType(OperateLog.LOG_SYS_LOG);// 从 func中获取roleType /home/home
                } else {
                    String pageUrl = request.getParameter(PAGE_URL_PARAM);
                    func = FuncDao.getFunc(pageUrl);
                    if (func != null && func.getIsLoad()) {
                        operateLog.setFuncId(func.getId());
                        operateLog.setPageName(func.getFuncName());
                        operateLog.setPageUrl(pageUrl);
                        if (func.getSysRoleType() != null) {
                            operateLog.setRoleType(func.getSysRoleType());// 从 func中获取roleType
                        }
                    }
                    String operateName = getOperateNameByActionName(action, packageName, nameSpace, actionName);
                    if (StringUtils.isBlank(operateName)) {
                        operateName = "其他操作";
                    }
                    operateLog.setOperatName(operateName);
                }
            }
            operateLog.setRemoteAddr(HostUtility.getClientIP(request));
            operateLog.setActionName(actionName);
            operateLog.setCreateTime(new Date());
            operateLog.setServerIp(HostUtility.getlocalHostAddress());
            if (action.getCommonException() != null) {
                ByteArrayOutputStream bo = new ByteArrayOutputStream();
                action.getCommonException().printStackTrace(new PrintStream(bo));
                bo.toString();
                operateLog.setException(bo.toString().substring(0, 1000));
                operateLog.setInfo(action.getCommonException().getErrorInfo());
                operateLog.setStatusCode(action.getCommonException().getErrorCode());
            } else {
                operateLog.setStatusCode(responseVo.getStatus());
                if (responseVo.getData() != null) {
                    String json = JSONUtility.objectToJson(responseVo.getData());
                    if (json.length() > 1000) {
                        operateLog.setInfo(json.substring(0, 1000));
                    } else {
                        operateLog.setInfo(json);
                    }
                }
            }
            if (action != null && action.getModel() != null) {
                operateLog.setActionVoType(action.getModel().getClass().getName());
                operateLog.setActionVoId(Utility.toObject(Utility.toString(ReflectionUtils.invokeMethod(action.getModel(), "getId")), Long.class));
                String json = JSONUtility.objectToJson(action.getModel());
                if (json.length() > 2000) {
                    operateLog.setActionVoParams(json.substring(0, 2000));
                } else {
                    operateLog.setActionVoParams(json);
                }
            } else {
                try {
                    if (StringUtils.isNotBlank(referer)) {
                        operateLog.setActionVoParams(URLDecoder.decode(referer, "utf-8"));
                    }
                } catch (UnsupportedEncodingException e) {
                    logger.error(e, e);
                }
            }

            new CommonThread("", "operateLog") {
                public void run() {
                    try {
                        operateLog.update();
                    } catch (Exception e) {
                        logger.error("记录操作日志update异常:", e);
                    }
                }
            }.start();
        }
    }


文章来源:https://blog.csdn.net/dongjing991/article/details/144562433
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!

标签:

相关文章

本站推荐

标签云