package com.dsh.other.audit; import com.alibaba.fastjson.JSON; import com.dsh.other.entity.SysAccountAuditLog; import org.apache.commons.lang3.StringUtils; import javax.servlet.http.HttpServletRequest; import java.util.LinkedHashMap; import java.util.Map; import java.util.UUID; final class AuditLogSupport { private AuditLogSupport() { } static final String TRACE_HEADER = "X-Audit-Trace-Id"; static SysAccountAuditLog fromRequest(HttpServletRequest request) { String uri = request.getRequestURI(); String method = request.getMethod(); SysAccountAuditLog log = new SysAccountAuditLog(); log.setTraceId(StringUtils.defaultIfBlank(request.getHeader(TRACE_HEADER), UUID.randomUUID().toString().replace("-", ""))); log.setUserId(toLong(request.getHeader("userId"))); // 账号列用于定位操作人,不能保存为 a***in 这类不可检索的掩码值。 log.setUserAccount(request.getHeader("username")); log.setSourceService("mb-cloud-other"); log.setSourceType("HTTP"); log.setRequestMethod(method); log.setRequestUri(uri); log.setRequestParams(maskParameters(request.getParameterMap())); log.setClientIp(clientIp(request)); log.setOperationType(operationType(method, uri)); log.setRiskLevel(riskLevel(uri, log.getOperationType())); log.setOperationName(method + " " + uri); return log; } static String operationType(String method, String uri) { String value = (uri == null ? "" : uri).toLowerCase(); if (value.contains("login") || value.contains("token")) return "LOGIN"; if (value.matches(".*(status|state|ticket|payment|finance|refund|withdraw|balance|order).*")) return "STATUS_CHANGE"; if ("POST".equalsIgnoreCase(method)) return "CREATE"; if ("PUT".equalsIgnoreCase(method) || "PATCH".equalsIgnoreCase(method)) return "UPDATE"; if ("DELETE".equalsIgnoreCase(method)) return "DELETE"; if (value.matches(".*(phone|mobile|idcard|identity|bank|wallet|finance|payment|ticket).*")) return "VIEW_SENSITIVE"; return "READ"; } static String riskLevel(String uri, String operationType) { String value = (uri == null ? "" : uri).toLowerCase(); if ("STATUS_CHANGE".equals(operationType) || value.matches(".*(finance|payment|refund|withdraw|balance|ticket).*")) return "CRITICAL"; if ("VIEW_SENSITIVE".equals(operationType) || value.matches(".*(phone|mobile|idcard|identity|bank|wallet).*")) return "SENSITIVE"; return "NORMAL"; } static String maskParameters(Map parameters) { Map result = new LinkedHashMap(); for (Map.Entry entry : parameters.entrySet()) { String key = entry.getKey(); result.put(key, isSensitiveKey(key) ? "***" : entry.getValue()); } return JSON.toJSONString(result); } static String maskText(String text) { return text == null ? null : text.replaceAll("(?i)(password|token|authorization|idcard|bankCard)\\s*[:=]\\s*[^,\\s&}]+", "$1=***"); } static boolean isSensitiveKey(String key) { return key != null && key.toLowerCase().matches(".*(password|token|authorization|secret|idcard|identity|bank|card|mobile|phone).*" ); } static Long toLong(String value) { try { return StringUtils.isBlank(value) ? null : Long.valueOf(value); } catch (NumberFormatException e) { return null; } } static String clientIp(HttpServletRequest request) { String ip = request.getHeader("X-Forwarded-For"); return StringUtils.isBlank(ip) ? request.getRemoteAddr() : ip.split(",")[0].trim(); } }