参数校验
This commit is contained in:
280
src/main/java/com/greenorange/promotion/aop/OperLogAspect.java
Normal file
280
src/main/java/com/greenorange/promotion/aop/OperLogAspect.java
Normal file
@ -0,0 +1,280 @@
|
||||
package com.greenorange.promotion.aop;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.greenorange.promotion.annotation.MyLog;
|
||||
import com.greenorange.promotion.model.entity.SysOperLog;
|
||||
import com.greenorange.promotion.service.log.SysOperLogService;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.*;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 切面处理类,记录操作日志到数据库
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
public class OperLogAspect {
|
||||
|
||||
@Resource
|
||||
private SysOperLogService sysOperLogService;
|
||||
|
||||
// 为了记录方法的执行时间
|
||||
ThreadLocal<Long> startTime = new ThreadLocal<>();
|
||||
|
||||
|
||||
@Before("@annotation(myLog)")
|
||||
public void beforeMethod(JoinPoint joinPoint, MyLog myLog){
|
||||
startTime.set(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 正常返回通知,拦截用户操作日志,连接点正常执行完成后执行, 如果连接点抛出异常,则不会执行
|
||||
* @param joinPoint 切入点
|
||||
* @param result 返回结果
|
||||
*/
|
||||
@AfterReturning(value = "@annotation(myLog)", returning = "result")
|
||||
public void saveOperLog(JoinPoint joinPoint, MyLog myLog, Object result) {
|
||||
// 获取RequestAttributes
|
||||
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
|
||||
// 从获取RequestAttributes中获取HttpServletRequest的信息
|
||||
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
|
||||
try {
|
||||
// 从切面织入点处通过反射机制获取织入点处的方法
|
||||
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||
// 获取切入点所在的方法
|
||||
Method method = signature.getMethod();
|
||||
// 获取操作
|
||||
SysOperLog sysOperLog = new SysOperLog();
|
||||
sysOperLog.setTitle(myLog.title());//设置模块名称
|
||||
sysOperLog.setContent(myLog.content());//设置日志内容
|
||||
// 将入参转换成json
|
||||
String params = argsArrayToString(joinPoint.getArgs());
|
||||
// 获取请求的类名
|
||||
String className = joinPoint.getTarget().getClass().getName();
|
||||
// 获取请求的方法名
|
||||
String methodName = method.getName();
|
||||
methodName = className + "." + methodName + "()";
|
||||
sysOperLog.setMethod(methodName); //设置请求方法
|
||||
sysOperLog.setRequestMethod(request.getMethod());//设置请求方式
|
||||
sysOperLog.setRequestParam(params); // 请求参数
|
||||
sysOperLog.setResponseResult(JSON.toJSONString(result)); // 返回结果
|
||||
// 从request中取出账号
|
||||
String userAccount = (String) request.getAttribute("userAccount");
|
||||
sysOperLog.setOperName(userAccount); // 获取用户名(真实环境中,肯定有工具类获取当前登录者的账号或ID的,或者从token中解析而来)
|
||||
String ip = getIp(request);
|
||||
sysOperLog.setIp(ip); // IP地址
|
||||
String ipLocation = getIpLocation(ip);
|
||||
sysOperLog.setIpLocation(ipLocation); // IP归属地(真是环境中可以调用第三方API根据IP地址,查询归属地)
|
||||
sysOperLog.setRequestUrl(request.getRequestURI()); // 请求URI
|
||||
sysOperLog.setOperTime(new Date()); // 时间
|
||||
sysOperLog.setStatus(0);//操作状态(0正常 1异常)
|
||||
Long takeTime = System.currentTimeMillis() - startTime.get();//记录方法执行耗时时间(单位:毫秒)
|
||||
sysOperLog.setTakeTime(takeTime);
|
||||
//插入数据库
|
||||
sysOperLogService.save(sysOperLog);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置操作异常切入点记录异常日志 扫描所有controller包下操作
|
||||
* 异常返回通知,用于拦截异常日志信息 连接点抛出异常后执行
|
||||
*/
|
||||
@AfterThrowing(pointcut = "execution(* com.greenorange.promotion.controller..*.*(..))", throwing = "e")
|
||||
public void saveExceptionLog(JoinPoint joinPoint, Throwable e) {
|
||||
// 获取RequestAttributes
|
||||
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
|
||||
// 从获取RequestAttributes中获取HttpServletRequest的信息
|
||||
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
|
||||
|
||||
SysOperLog sysOperLog = new SysOperLog();
|
||||
try {
|
||||
// 从切面织入点处通过反射机制获取织入点处的方法
|
||||
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||
// 获取切入点所在的方法
|
||||
Method method = signature.getMethod();
|
||||
// 获取请求的类名
|
||||
String className = joinPoint.getTarget().getClass().getName();
|
||||
// 获取请求的方法名
|
||||
String methodName = method.getName();
|
||||
methodName = className + "." + methodName + "()";
|
||||
// 获取操作
|
||||
MyLog myLog = method.getAnnotation(MyLog.class);
|
||||
if (myLog != null) {
|
||||
sysOperLog.setTitle(myLog.title());//设置模块名称
|
||||
sysOperLog.setContent(myLog.content());//设置日志内容
|
||||
}
|
||||
// 将入参转换成json
|
||||
String params = argsArrayToString(joinPoint.getArgs());
|
||||
sysOperLog.setMethod(methodName); //设置请求方法
|
||||
sysOperLog.setRequestMethod(request.getMethod());//设置请求方式
|
||||
sysOperLog.setRequestParam(params); // 请求参数
|
||||
// 从request中取出账号
|
||||
String userAccount = (String) request.getAttribute("userAccount");
|
||||
sysOperLog.setOperName(userAccount); // 获取用户名(真实环境中,肯定有工具类获取当前登录者的账号或ID的,或者从token中解析而来)
|
||||
String ip = getIp(request);
|
||||
sysOperLog.setIp(ip); // IP地址
|
||||
String ipLocation = getIpLocation(ip);
|
||||
sysOperLog.setIpLocation(ipLocation); // IP归属地(真是环境中可以调用第三方API根据IP地址,查询归属地)
|
||||
sysOperLog.setRequestUrl(request.getRequestURI()); // 请求URI
|
||||
sysOperLog.setOperTime(new Date()); // 时间
|
||||
sysOperLog.setStatus(1);//操作状态(0正常 1异常)
|
||||
sysOperLog.setErrorMsg(stackTraceToString(e.getClass().getName(), e.getMessage(), e.getStackTrace()));//记录异常信息
|
||||
//插入数据库
|
||||
sysOperLogService.save(sysOperLog);
|
||||
} catch (Exception e2) {
|
||||
e2.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换异常信息为字符串
|
||||
*/
|
||||
public String stackTraceToString(String exceptionName, String exceptionMessage, StackTraceElement[] elements) {
|
||||
StringBuffer strbuff = new StringBuffer();
|
||||
for (StackTraceElement stet : elements) {
|
||||
strbuff.append(stet + "\n");
|
||||
}
|
||||
String message = exceptionName + ":" + exceptionMessage + "\n\t" + strbuff.toString();
|
||||
message = substring(message,0 ,2000);
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数拼装
|
||||
*/
|
||||
private String argsArrayToString(Object[] paramsArray)
|
||||
{
|
||||
String params = "";
|
||||
if (paramsArray != null && paramsArray.length > 0) {
|
||||
for (Object o : paramsArray) {
|
||||
if (o != null) {
|
||||
try {
|
||||
Object jsonObj = JSON.toJSON(o);
|
||||
params += jsonObj.toString() + " ";
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return params.trim();
|
||||
}
|
||||
|
||||
//字符串截取
|
||||
public static String substring(String str, int start, int end) {
|
||||
if (str == null) {
|
||||
return null;
|
||||
} else {
|
||||
if (end < 0) {
|
||||
end += str.length();
|
||||
}
|
||||
|
||||
if (start < 0) {
|
||||
start += str.length();
|
||||
}
|
||||
|
||||
if (end > str.length()) {
|
||||
end = str.length();
|
||||
}
|
||||
|
||||
if (start > end) {
|
||||
return "";
|
||||
} else {
|
||||
if (start < 0) {
|
||||
start = 0;
|
||||
}
|
||||
|
||||
if (end < 0) {
|
||||
end = 0;
|
||||
}
|
||||
return str.substring(start, end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换request 请求参数
|
||||
* @param paramMap request获取的参数数组
|
||||
*/
|
||||
public Map<String, String> converMap(Map<String, String[]> paramMap) {
|
||||
Map<String, String> returnMap = new HashMap<>();
|
||||
for (String key : paramMap.keySet()) {
|
||||
returnMap.put(key, paramMap.get(key)[0]);
|
||||
}
|
||||
return returnMap;
|
||||
}
|
||||
|
||||
//根据HttpServletRequest获取访问者的IP地址
|
||||
public String getIp(HttpServletRequest request) {
|
||||
String ip = request.getHeader("x-forwarded-for");
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("Proxy-Client-IP");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("WL-Proxy-Client-IP");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("HTTP_CLIENT_IP");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getRemoteAddr();
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getIpLocation(String ip) {
|
||||
try {
|
||||
// 发送请求到ip-api服务
|
||||
String url = "http://ip-api.com/json/" + ip + "?lang=zh-CN"; // 获取中文结果
|
||||
URL obj = new URL(url);
|
||||
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
|
||||
con.setRequestMethod("GET");
|
||||
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
|
||||
String inputLine;
|
||||
StringBuffer response = new StringBuffer();
|
||||
|
||||
while ((inputLine = in.readLine()) != null) {
|
||||
response.append(inputLine);
|
||||
}
|
||||
in.close();
|
||||
|
||||
// 解析JSON返回结果
|
||||
JSONObject jsonResponse = JSONObject.parseObject(response.toString());
|
||||
String region = jsonResponse.getString("regionName"); // 省
|
||||
String city = jsonResponse.getString("city"); // 城市
|
||||
String country = jsonResponse.getString("country"); // 国家
|
||||
|
||||
return city + ", " + region + ", " + country; // 返回位置
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "未知";
|
||||
}
|
||||
|
||||
}
|
@ -66,6 +66,8 @@ public class PermissionCheck {
|
||||
DecodedJWT decodedJWT = jwtUtils.verify(token);
|
||||
String userAccount = decodedJWT.getClaim("userAccount").asString();
|
||||
String userPassword = decodedJWT.getClaim("userPassword").asString();
|
||||
// 将账号存入request,用于记录日志
|
||||
request.setAttribute("userAccount", userAccount);
|
||||
// 打印token的过期时间
|
||||
Date expiresAt = decodedJWT.getExpiresAt();
|
||||
String formatExpiresAt = DateUtil.format(expiresAt, "yyyy-MM-dd HH:mm:ss");
|
||||
|
Reference in New Issue
Block a user