perf: 优化系统日志参数获取,优化在线用户Token管理,优化SQl日志打印
This commit is contained in:
parent
1f54a5425f
commit
25e5b553e0
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
### IDEA ###
|
||||||
|
.idea/*
|
||||||
|
.DS_Store
|
||||||
|
application.pid
|
@ -23,6 +23,8 @@
|
|||||||
<!--表格渲染-->
|
<!--表格渲染-->
|
||||||
<el-table ref="table" v-loading="crud.loading" :data="crud.data" style="width: 100%;" @selection-change="crud.selectionChangeHandler">
|
<el-table ref="table" v-loading="crud.loading" :data="crud.data" style="width: 100%;" @selection-change="crud.selectionChangeHandler">
|
||||||
<el-table-column type="selection" width="55" />
|
<el-table-column type="selection" width="55" />
|
||||||
|
|
||||||
|
<el-table-column :show-overflow-tooltip="true" prop="uid" label="会话编号" />
|
||||||
<el-table-column prop="userName" label="用户名" />
|
<el-table-column prop="userName" label="用户名" />
|
||||||
<el-table-column prop="nickName" label="用户昵称" />
|
<el-table-column prop="nickName" label="用户昵称" />
|
||||||
<el-table-column prop="dept" label="部门" />
|
<el-table-column prop="dept" label="部门" />
|
||||||
|
1
eladmin/.gitignore
vendored
1
eladmin/.gitignore
vendored
@ -1,4 +1,5 @@
|
|||||||
### IDEA ###
|
### IDEA ###
|
||||||
|
.DS_Store
|
||||||
~/*
|
~/*
|
||||||
.idea/*
|
.idea/*
|
||||||
*.iml
|
*.iml
|
||||||
|
@ -32,7 +32,6 @@ import java.util.*;
|
|||||||
* 字符串工具类, 继承org.apache.commons.lang3.StringUtils类
|
* 字符串工具类, 继承org.apache.commons.lang3.StringUtils类
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@SuppressWarnings({"all"})
|
|
||||||
public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||||
|
|
||||||
private static final char SEPARATOR = '_';
|
private static final char SEPARATOR = '_';
|
||||||
@ -133,13 +132,13 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
|||||||
*/
|
*/
|
||||||
public static String getIp(HttpServletRequest request) {
|
public static String getIp(HttpServletRequest request) {
|
||||||
String ip = request.getHeader("x-forwarded-for");
|
String ip = request.getHeader("x-forwarded-for");
|
||||||
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
|
if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) {
|
||||||
ip = request.getHeader("Proxy-Client-IP");
|
ip = request.getHeader("Proxy-Client-IP");
|
||||||
}
|
}
|
||||||
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
|
if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) {
|
||||||
ip = request.getHeader("WL-Proxy-Client-IP");
|
ip = request.getHeader("WL-Proxy-Client-IP");
|
||||||
}
|
}
|
||||||
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
|
if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) {
|
||||||
ip = request.getRemoteAddr();
|
ip = request.getRemoteAddr();
|
||||||
}
|
}
|
||||||
String comma = ",";
|
String comma = ",";
|
||||||
@ -169,6 +168,9 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取浏览器
|
||||||
|
*/
|
||||||
public static String getBrowser(HttpServletRequest request) {
|
public static String getBrowser(HttpServletRequest request) {
|
||||||
UserAgent ua = UserAgentUtil.parse(request.getHeader("User-Agent"));
|
UserAgent ua = UserAgentUtil.parse(request.getHeader("User-Agent"));
|
||||||
String browser = ua.getBrowser().toString() + " " + ua.getVersion();
|
String browser = ua.getBrowser().toString() + " " + ua.getVersion();
|
||||||
@ -230,6 +232,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"all"})
|
||||||
public static List<Field> getAllFields(Class clazz, List<Field> fields) {
|
public static List<Field> getAllFields(Class clazz, List<Field> fields) {
|
||||||
if (clazz != null) {
|
if (clazz != null) {
|
||||||
fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
|
fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
|
||||||
|
@ -88,6 +88,10 @@ public class LogAspect {
|
|||||||
sysLogService.save(getUsername(), StringUtils.getBrowser(request), StringUtils.getIp(request), (ProceedingJoinPoint)joinPoint, sysLog);
|
sysLogService.save(getUsername(), StringUtils.getBrowser(request), StringUtils.getIp(request), (ProceedingJoinPoint)joinPoint, sysLog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户名
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
public String getUsername() {
|
public String getUsername() {
|
||||||
try {
|
try {
|
||||||
return SecurityUtils.getCurrentUsername();
|
return SecurityUtils.getCurrentUsername();
|
||||||
|
@ -32,8 +32,8 @@ import org.springframework.scheduling.annotation.Async;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
@ -47,7 +47,10 @@ import java.util.*;
|
|||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class SysLogServiceImpl extends ServiceImpl<SysLogMapper, SysLog> implements SysLogService {
|
public class SysLogServiceImpl extends ServiceImpl<SysLogMapper, SysLog> implements SysLogService {
|
||||||
|
|
||||||
private final SysLogMapper sysLogMapper;
|
private final SysLogMapper sysLogMapper;
|
||||||
|
// 定义敏感字段常量数组
|
||||||
|
private static final String[] SENSITIVE_KEYS = {"password"};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageResult<SysLog> queryAll(SysLogQueryCriteria criteria, Page<SysLog> page) {
|
public PageResult<SysLog> queryAll(SysLogQueryCriteria criteria, Page<SysLog> page) {
|
||||||
@ -71,6 +74,8 @@ public class SysLogServiceImpl extends ServiceImpl<SysLogMapper, SysLog> impleme
|
|||||||
if (sysLog == null) {
|
if (sysLog == null) {
|
||||||
throw new IllegalArgumentException("Log 不能为 null!");
|
throw new IllegalArgumentException("Log 不能为 null!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取方法签名
|
||||||
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||||
Method method = signature.getMethod();
|
Method method = signature.getMethod();
|
||||||
me.zhengjie.annotation.Log aopLog = method.getAnnotation(me.zhengjie.annotation.Log.class);
|
me.zhengjie.annotation.Log aopLog = method.getAnnotation(me.zhengjie.annotation.Log.class);
|
||||||
@ -78,21 +83,23 @@ public class SysLogServiceImpl extends ServiceImpl<SysLogMapper, SysLog> impleme
|
|||||||
// 方法路径
|
// 方法路径
|
||||||
String methodName = joinPoint.getTarget().getClass().getName() + "." + signature.getName() + "()";
|
String methodName = joinPoint.getTarget().getClass().getName() + "." + signature.getName() + "()";
|
||||||
|
|
||||||
// 描述
|
// 获取参数
|
||||||
sysLog.setDescription(aopLog.value());
|
JSONObject params = getParameter(method, joinPoint.getArgs());
|
||||||
|
|
||||||
|
// 填充基本信息
|
||||||
sysLog.setRequestIp(ip);
|
sysLog.setRequestIp(ip);
|
||||||
sysLog.setAddress(StringUtils.getCityInfo(sysLog.getRequestIp()));
|
sysLog.setAddress(StringUtils.getCityInfo(sysLog.getRequestIp()));
|
||||||
sysLog.setMethod(methodName);
|
sysLog.setMethod(methodName);
|
||||||
sysLog.setUsername(username);
|
sysLog.setUsername(username);
|
||||||
sysLog.setParams(getParameter(method, joinPoint.getArgs()));
|
sysLog.setParams(JSON.toJSONString(params));
|
||||||
// 记录登录用户,隐藏密码信息
|
|
||||||
if(signature.getName().equals("login") && StringUtils.isNotEmpty(sysLog.getParams())){
|
|
||||||
JSONObject obj = JSON.parseObject(sysLog.getParams());
|
|
||||||
sysLog.setUsername(obj.getString("username"));
|
|
||||||
sysLog.setParams(JSON.toJSONString(Dict.create().set("username", sysLog.getUsername())));
|
|
||||||
}
|
|
||||||
sysLog.setBrowser(browser);
|
sysLog.setBrowser(browser);
|
||||||
|
sysLog.setDescription(aopLog.value());
|
||||||
|
|
||||||
|
// 如果没有获取到用户名,尝试从参数中获取
|
||||||
|
if(StringUtils.isBlank(sysLog.getUsername())){
|
||||||
|
sysLog.setUsername(params.getString("username"));
|
||||||
|
}
|
||||||
|
|
||||||
// 保存
|
// 保存
|
||||||
save(sysLog);
|
save(sysLog);
|
||||||
}
|
}
|
||||||
@ -100,35 +107,40 @@ public class SysLogServiceImpl extends ServiceImpl<SysLogMapper, SysLog> impleme
|
|||||||
/**
|
/**
|
||||||
* 根据方法和传入的参数获取请求参数
|
* 根据方法和传入的参数获取请求参数
|
||||||
*/
|
*/
|
||||||
private String getParameter(Method method, Object[] args) {
|
private JSONObject getParameter(Method method, Object[] args) {
|
||||||
List<Object> argList = new ArrayList<>();
|
JSONObject params = new JSONObject();
|
||||||
Parameter[] parameters = method.getParameters();
|
Parameter[] parameters = method.getParameters();
|
||||||
for (int i = 0; i < parameters.length; i++) {
|
for (int i = 0; i < parameters.length; i++) {
|
||||||
// 过滤掉不能序列化的类型: MultiPartFile
|
// 过滤掉 MultiPartFile
|
||||||
if (args[i] instanceof MultipartFile) {
|
if (args[i] instanceof MultipartFile) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//将RequestBody注解修饰的参数作为请求参数
|
// 过滤掉 HttpServletResponse
|
||||||
|
if (args[i] instanceof HttpServletResponse) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 过滤掉 HttpServletRequest
|
||||||
|
if (args[i] instanceof HttpServletRequest) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 将RequestBody注解修饰的参数作为请求参数
|
||||||
RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);
|
RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);
|
||||||
if (requestBody != null) {
|
if (requestBody != null) {
|
||||||
argList.add(args[i]);
|
params.putAll((JSONObject) JSON.toJSON(args[i]));
|
||||||
}
|
} else {
|
||||||
//将RequestParam注解修饰的参数作为请求参数
|
|
||||||
RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class);
|
|
||||||
if (requestParam != null) {
|
|
||||||
Map<String, Object> map = new HashMap<>(2);
|
|
||||||
String key = parameters[i].getName();
|
String key = parameters[i].getName();
|
||||||
if (!StringUtils.isEmpty(requestParam.value())) {
|
params.put(key, args[i]);
|
||||||
key = requestParam.value();
|
|
||||||
}
|
|
||||||
map.put(key, args[i]);
|
|
||||||
argList.add(map);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (argList.isEmpty()) {
|
// 遍历敏感字段数组并替换值
|
||||||
return "";
|
Set<String> keys = params.keySet();
|
||||||
|
for (String key : SENSITIVE_KEYS) {
|
||||||
|
if (keys.contains(key)) {
|
||||||
|
params.put(key, "******");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return argList.size() == 1 ? JSON.toJSONString(argList.get(0)) : JSON.toJSONString(argList);
|
// 返回参数
|
||||||
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -18,7 +18,6 @@ package me.zhengjie.modules.security.security;
|
|||||||
import cn.hutool.core.date.DateField;
|
import cn.hutool.core.date.DateField;
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
import cn.hutool.core.util.IdUtil;
|
import cn.hutool.core.util.IdUtil;
|
||||||
import cn.hutool.crypto.digest.DigestUtil;
|
|
||||||
import io.jsonwebtoken.*;
|
import io.jsonwebtoken.*;
|
||||||
import io.jsonwebtoken.io.Decoders;
|
import io.jsonwebtoken.io.Decoders;
|
||||||
import io.jsonwebtoken.security.Keys;
|
import io.jsonwebtoken.security.Keys;
|
||||||
@ -49,7 +48,7 @@ public class TokenProvider implements InitializingBean {
|
|||||||
private JwtBuilder jwtBuilder;
|
private JwtBuilder jwtBuilder;
|
||||||
private final RedisUtils redisUtils;
|
private final RedisUtils redisUtils;
|
||||||
private final SecurityProperties properties;
|
private final SecurityProperties properties;
|
||||||
public static final String AUTHORITIES_UUID_KEY = "uuid";
|
public static final String AUTHORITIES_UUID_KEY = "uid";
|
||||||
public static final String AUTHORITIES_UID_KEY = "userId";
|
public static final String AUTHORITIES_UID_KEY = "userId";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -75,7 +74,7 @@ public class TokenProvider implements InitializingBean {
|
|||||||
// 设置用户ID
|
// 设置用户ID
|
||||||
claims.put(AUTHORITIES_UID_KEY, user.getUser().getId());
|
claims.put(AUTHORITIES_UID_KEY, user.getUser().getId());
|
||||||
// 设置UUID,确保每次Token不一样
|
// 设置UUID,确保每次Token不一样
|
||||||
claims.put(AUTHORITIES_UUID_KEY, IdUtil.simpleUUID());
|
claims.put(AUTHORITIES_UUID_KEY, IdUtil.objectId());
|
||||||
return jwtBuilder
|
return jwtBuilder
|
||||||
.setClaims(claims)
|
.setClaims(claims)
|
||||||
.setSubject(user.getUsername())
|
.setSubject(user.getUsername())
|
||||||
@ -132,7 +131,16 @@ public class TokenProvider implements InitializingBean {
|
|||||||
*/
|
*/
|
||||||
public String loginKey(String token) {
|
public String loginKey(String token) {
|
||||||
Claims claims = getClaims(token);
|
Claims claims = getClaims(token);
|
||||||
String md5Token = DigestUtil.md5Hex(token);
|
return properties.getOnlineKey() + claims.getSubject() + ":" + getId(token);
|
||||||
return properties.getOnlineKey() + claims.getSubject() + "-" + md5Token;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取会话编号
|
||||||
|
* @param token /
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public String getId(String token) {
|
||||||
|
Claims claims = getClaims(token);
|
||||||
|
return claims.get(AUTHORITIES_UUID_KEY, String.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,11 +53,12 @@ public class OnlineUserService {
|
|||||||
public void save(JwtUserDto jwtUserDto, String token, HttpServletRequest request){
|
public void save(JwtUserDto jwtUserDto, String token, HttpServletRequest request){
|
||||||
String dept = jwtUserDto.getUser().getDept().getName();
|
String dept = jwtUserDto.getUser().getDept().getName();
|
||||||
String ip = StringUtils.getIp(request);
|
String ip = StringUtils.getIp(request);
|
||||||
|
String id = tokenProvider.getId(token);
|
||||||
String browser = StringUtils.getBrowser(request);
|
String browser = StringUtils.getBrowser(request);
|
||||||
String address = StringUtils.getCityInfo(ip);
|
String address = StringUtils.getCityInfo(ip);
|
||||||
OnlineUserDto onlineUserDto = null;
|
OnlineUserDto onlineUserDto = null;
|
||||||
try {
|
try {
|
||||||
onlineUserDto = new OnlineUserDto(jwtUserDto.getUsername(), jwtUserDto.getUser().getNickName(), dept, browser , ip, address, EncryptUtils.desEncrypt(token), new Date());
|
onlineUserDto = new OnlineUserDto(id, jwtUserDto.getUsername(), jwtUserDto.getUser().getNickName(), dept, browser , ip, address, EncryptUtils.desEncrypt(token), new Date());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error(e.getMessage(),e);
|
log.error(e.getMessage(),e);
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,9 @@ import java.util.Date;
|
|||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class OnlineUserDto {
|
public class OnlineUserDto {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "Token编号")
|
||||||
|
private String uid;
|
||||||
|
|
||||||
@ApiModelProperty(value = "用户名")
|
@ApiModelProperty(value = "用户名")
|
||||||
private String userName;
|
private String userName;
|
||||||
|
|
||||||
|
@ -15,6 +15,6 @@ outagedetectioninterval=2
|
|||||||
# 是否过滤 Log
|
# 是否过滤 Log
|
||||||
filter=true
|
filter=true
|
||||||
# 过滤 Log 时所排除的 sql 关键字,以逗号分隔
|
# 过滤 Log 时所排除的 sql 关键字,以逗号分隔
|
||||||
exclude=select 1
|
exclude=SELECT 1,INSERT INTO sys_log
|
||||||
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
|
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
|
||||||
excludecategories=info,debug,result,commit,resultset
|
excludecategories=info,debug,result,commit,resultset
|
Loading…
Reference in New Issue
Block a user