操作日志自动记录参数.
This commit is contained in:
@@ -26,6 +26,13 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- web -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.orion.ops.framework.biz.operator.log.core.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 用于记录操作日志时候 忽略参数
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2023/10/11 17:45
|
||||
*/
|
||||
@Target({ElementType.PARAMETER})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface IgnoreParameter {
|
||||
|
||||
}
|
||||
@@ -21,6 +21,19 @@ public @interface OperatorLog {
|
||||
*/
|
||||
String value();
|
||||
|
||||
/**
|
||||
* 是否记录参数
|
||||
* <p>
|
||||
* - {@link org.springframework.web.bind.annotation.RequestBody}
|
||||
* - {@link org.springframework.web.bind.annotation.RequestParam}
|
||||
* - {@link org.springframework.web.bind.annotation.RequestHeader}
|
||||
* - {@link org.springframework.web.bind.annotation.PathVariable}
|
||||
* <p>
|
||||
* 使用 @IgnoreParameter 可以忽略参数记录 {@link IgnoreParameter}
|
||||
* 如果只需要忽略某个字段可以使用 @Desensitize(toEmpty = true) 标注
|
||||
*/
|
||||
boolean parameter() default true;
|
||||
|
||||
/**
|
||||
* 返回值处理
|
||||
*/
|
||||
|
||||
@@ -4,8 +4,10 @@ import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.serializer.ValueFilter;
|
||||
import com.orion.lang.define.thread.ExecutorBuilder;
|
||||
import com.orion.lang.define.wrapper.Ref;
|
||||
import com.orion.lang.utils.Arrays1;
|
||||
import com.orion.lang.utils.Strings;
|
||||
import com.orion.lang.utils.json.matcher.ReplacementFormatters;
|
||||
import com.orion.ops.framework.biz.operator.log.core.annotation.IgnoreParameter;
|
||||
import com.orion.ops.framework.biz.operator.log.core.annotation.OperatorLog;
|
||||
import com.orion.ops.framework.biz.operator.log.core.config.OperatorLogConfig;
|
||||
import com.orion.ops.framework.biz.operator.log.core.enums.ReturnType;
|
||||
@@ -16,6 +18,7 @@ import com.orion.ops.framework.biz.operator.log.core.service.OperatorLogFramewor
|
||||
import com.orion.ops.framework.biz.operator.log.core.uitls.OperatorLogs;
|
||||
import com.orion.ops.framework.common.enums.BooleanBit;
|
||||
import com.orion.ops.framework.common.meta.TraceIdHolder;
|
||||
import com.orion.ops.framework.common.security.LoginUser;
|
||||
import com.orion.ops.framework.common.security.SecurityHolder;
|
||||
import com.orion.ops.framework.common.utils.IpUtils;
|
||||
import com.orion.web.servlet.web.Servlets;
|
||||
@@ -23,14 +26,19 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
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 java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
/**
|
||||
@@ -71,9 +79,9 @@ public class OperatorLogAspect {
|
||||
@Around("@annotation(o)")
|
||||
public Object around(ProceedingJoinPoint joinPoint, OperatorLog o) throws Throwable {
|
||||
long start = System.currentTimeMillis();
|
||||
// 先清空上下文
|
||||
OperatorLogs.clear();
|
||||
try {
|
||||
// 初始化参数
|
||||
this.initExtra(joinPoint, o);
|
||||
// 执行
|
||||
Object result = joinPoint.proceed();
|
||||
// 记录日志
|
||||
@@ -89,6 +97,71 @@ public class OperatorLogAspect {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化参数
|
||||
*
|
||||
* @param joinPoint joinPoint
|
||||
*/
|
||||
private void initExtra(ProceedingJoinPoint joinPoint, OperatorLog o) {
|
||||
// 清空上下文
|
||||
OperatorLogs.clear();
|
||||
if (!o.parameter()) {
|
||||
return;
|
||||
}
|
||||
// 获取方法注解
|
||||
Annotation[][] methodAnnotations = Optional.ofNullable(joinPoint.getSignature())
|
||||
.filter(s -> (s instanceof MethodSignature))
|
||||
.map(s -> ((MethodSignature) s).getMethod())
|
||||
.map(Method::getParameterAnnotations)
|
||||
.orElse(null);
|
||||
if (Arrays1.isEmpty(methodAnnotations)) {
|
||||
return;
|
||||
}
|
||||
// 获取参数
|
||||
Object[] args = joinPoint.getArgs();
|
||||
for (int i = 0; i < methodAnnotations.length; i++) {
|
||||
Annotation[] annotations = methodAnnotations[i];
|
||||
if (Arrays1.isEmpty(annotations)) {
|
||||
continue;
|
||||
}
|
||||
// 检查是否有 IgnoreParameter 注解
|
||||
boolean ignore = Arrays.stream(annotations)
|
||||
.anyMatch(s -> s instanceof IgnoreParameter);
|
||||
if (ignore) {
|
||||
continue;
|
||||
}
|
||||
// 获取需要记录的参数
|
||||
for (Annotation annotation : annotations) {
|
||||
if (annotation instanceof RequestBody) {
|
||||
OperatorLogs.add(args[i]);
|
||||
break;
|
||||
} else if (annotation instanceof RequestParam) {
|
||||
Object arg = args[i];
|
||||
if (arg instanceof MultipartFile) {
|
||||
break;
|
||||
}
|
||||
OperatorLogs.add(
|
||||
orElse(((RequestParam) annotation).value(),
|
||||
((RequestParam) annotation).name()),
|
||||
args[i]);
|
||||
break;
|
||||
} else if (annotation instanceof RequestHeader) {
|
||||
OperatorLogs.add(
|
||||
orElse(((RequestHeader) annotation).value(),
|
||||
((RequestHeader) annotation).name()),
|
||||
args[i]);
|
||||
break;
|
||||
} else if (annotation instanceof PathVariable) {
|
||||
OperatorLogs.add(
|
||||
orElse(((PathVariable) annotation).value(),
|
||||
((PathVariable) annotation).name()),
|
||||
args[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存日志
|
||||
*
|
||||
@@ -97,7 +170,17 @@ public class OperatorLogAspect {
|
||||
*/
|
||||
private void saveLog(long start, OperatorLog o, Object ret, Throwable exception) {
|
||||
try {
|
||||
// 请求信息
|
||||
// 获取日志类型
|
||||
OperatorType type = OperatorTypeHolder.get(o.value());
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
// 获取当前用户
|
||||
LoginUser user = this.getUser();
|
||||
if (user == null) {
|
||||
return;
|
||||
}
|
||||
// 获取请求信息
|
||||
Map<String, Object> extra = OperatorLogs.get();
|
||||
if (!OperatorLogs.isSave(extra)) {
|
||||
return;
|
||||
@@ -106,7 +189,7 @@ public class OperatorLogAspect {
|
||||
// 填充使用时间
|
||||
this.fillUseTime(model, start);
|
||||
// 填充用户信息
|
||||
this.fillUserInfo(model);
|
||||
this.fillUserInfo(model, user);
|
||||
// 填充请求信息
|
||||
this.fillRequest(model);
|
||||
// 填充结果信息
|
||||
@@ -114,7 +197,7 @@ public class OperatorLogAspect {
|
||||
// 填充拓展信息
|
||||
this.fillExtra(model, extra);
|
||||
// 填充日志
|
||||
this.fillLogInfo(model, extra, o);
|
||||
this.fillLogInfo(model, extra, type);
|
||||
// 插入日志
|
||||
this.asyncSaveLog(model);
|
||||
} catch (Exception e) {
|
||||
@@ -122,6 +205,20 @@ public class OperatorLogAspect {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户
|
||||
*
|
||||
* @return user
|
||||
*/
|
||||
private LoginUser getUser() {
|
||||
LoginUser user = OperatorLogs.getUser();
|
||||
if (user != null) {
|
||||
return user;
|
||||
}
|
||||
// 登录上下文获取
|
||||
return securityHolder.getLoginUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充使用时间
|
||||
*
|
||||
@@ -139,9 +236,11 @@ public class OperatorLogAspect {
|
||||
* 填充用户信息
|
||||
*
|
||||
* @param model model
|
||||
* @param user user
|
||||
*/
|
||||
private void fillUserInfo(OperatorLogModel model) {
|
||||
model.setUserId(securityHolder.getLoginUserId());
|
||||
private void fillUserInfo(OperatorLogModel model, LoginUser user) {
|
||||
model.setUserId(user.getId());
|
||||
model.setUsername(user.getUsername());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -205,10 +304,9 @@ public class OperatorLogAspect {
|
||||
*
|
||||
* @param model model
|
||||
* @param extra extra
|
||||
* @param o o
|
||||
* @param type type
|
||||
*/
|
||||
private void fillLogInfo(OperatorLogModel model, Map<String, Object> extra, OperatorLog o) {
|
||||
OperatorType type = OperatorTypeHolder.get(o.value());
|
||||
private void fillLogInfo(OperatorLogModel model, Map<String, Object> extra, OperatorType type) {
|
||||
model.setModule(type.getModule());
|
||||
model.setType(type.getType());
|
||||
model.setLogInfo(ReplacementFormatters.format(type.getTemplate(), extra));
|
||||
@@ -220,9 +318,18 @@ public class OperatorLogAspect {
|
||||
* @param model model
|
||||
*/
|
||||
private void asyncSaveLog(OperatorLogModel model) {
|
||||
LOG_SAVER.submit(() -> {
|
||||
operatorLogFrameworkService.insert(model);
|
||||
});
|
||||
LOG_SAVER.submit(() -> operatorLogFrameworkService.insert(model));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取可用值
|
||||
*
|
||||
* @param value value
|
||||
* @param name name
|
||||
* @return available
|
||||
*/
|
||||
private String orElse(String value, String name) {
|
||||
return Strings.isBlank(value) ? name : value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,10 @@ public interface OperatorLogKeys {
|
||||
|
||||
String NAME = "name";
|
||||
|
||||
String STATUS = "status";
|
||||
|
||||
String STATUS_NAME = "statusName";
|
||||
|
||||
String USERNAME = "username";
|
||||
|
||||
String TITLE = "title";
|
||||
|
||||
@@ -19,6 +19,11 @@ public class OperatorLogModel {
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* traceId
|
||||
*/
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.orion.ops.framework.biz.operator.log.core.uitls;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.serializer.ValueFilter;
|
||||
import com.orion.ops.framework.biz.operator.log.core.constant.OperatorLogKeys;
|
||||
import com.orion.ops.framework.common.security.LoginUser;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -20,8 +21,16 @@ public class OperatorLogs implements OperatorLogKeys {
|
||||
|
||||
private static ValueFilter desensitizeValueFilter;
|
||||
|
||||
/**
|
||||
* 拓展信息
|
||||
*/
|
||||
private static final ThreadLocal<Map<String, Object>> EXTRA_HOLDER = new ThreadLocal<>();
|
||||
|
||||
/**
|
||||
* 当前用户 优先于登录用户
|
||||
*/
|
||||
private static final ThreadLocal<LoginUser> USER_HOLDER = new ThreadLocal<>();
|
||||
|
||||
private OperatorLogs() {
|
||||
}
|
||||
|
||||
@@ -93,10 +102,11 @@ public class OperatorLogs implements OperatorLogKeys {
|
||||
*/
|
||||
public static void clear() {
|
||||
EXTRA_HOLDER.remove();
|
||||
USER_HOLDER.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否保存
|
||||
* 设置是否保存
|
||||
*
|
||||
* @param map map
|
||||
* @return save
|
||||
@@ -105,6 +115,24 @@ public class OperatorLogs implements OperatorLogKeys {
|
||||
return map == null || !map.containsKey(UN_SAVE_FLAG);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置用户信息
|
||||
*
|
||||
* @param user user
|
||||
*/
|
||||
public static void setUser(LoginUser user) {
|
||||
USER_HOLDER.set(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户
|
||||
*
|
||||
* @return user
|
||||
*/
|
||||
public static LoginUser getUser() {
|
||||
return USER_HOLDER.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*
|
||||
|
||||
@@ -23,6 +23,10 @@ import org.springframework.http.converter.json.MappingJackson2HttpMessageConvert
|
||||
public class OrionDesensitizeAutoConfiguration {
|
||||
|
||||
/**
|
||||
* 用于参数打印
|
||||
* - 全局日志打印
|
||||
* - 操作日志参数
|
||||
*
|
||||
* @return fastjson 序列化脱敏过滤器
|
||||
*/
|
||||
@Bean
|
||||
@@ -31,13 +35,14 @@ public class OrionDesensitizeAutoConfiguration {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return jackson 序列化脱敏过滤器
|
||||
* 用于 HTTP 响应序列化
|
||||
*
|
||||
* @return jackson 序列化脱敏序列化
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnBean(MappingJackson2HttpMessageConverter.class)
|
||||
public DesensitizeJsonSerializer desensitizeJsonSerializer(MappingJackson2HttpMessageConverter converter) {
|
||||
DesensitizeJsonSerializer serializer = new DesensitizeJsonSerializer();
|
||||
return serializer;
|
||||
public DesensitizeJsonSerializer desensitizeJsonSerializer() {
|
||||
return new DesensitizeJsonSerializer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@ import java.lang.annotation.*;
|
||||
/**
|
||||
* FastJson / Jackson 脱敏配置元注解
|
||||
* <p>
|
||||
* 标注在字段上则标记该字段执行 http 序列化时脱敏
|
||||
* Jackson 标注在字段上则标记该字段执行 http 序列化 (返回 VO)时脱敏 (http-message-converts 用的是 jackson)
|
||||
* FastJson 需要组合 {@link DesensitizeObject} 一起使用
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
@@ -22,6 +23,13 @@ import java.lang.annotation.*;
|
||||
@JsonSerialize(using = DesensitizeJsonSerializer.class)
|
||||
public @interface Desensitize {
|
||||
|
||||
/**
|
||||
* 一般用于操作日志参数脱敏
|
||||
*
|
||||
* @return 是否直接设置为空
|
||||
*/
|
||||
boolean toEmpty() default false;
|
||||
|
||||
/**
|
||||
* @return 起始保留字符数
|
||||
*/
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.orion.lang.utils.Strings;
|
||||
import com.orion.lang.utils.collect.Maps;
|
||||
import com.orion.lang.utils.reflect.Annotations;
|
||||
import com.orion.lang.utils.reflect.Fields;
|
||||
import com.orion.ops.framework.common.constant.Const;
|
||||
import com.orion.ops.framework.desensitize.core.annotation.Desensitize;
|
||||
import com.orion.ops.framework.desensitize.core.annotation.DesensitizeObject;
|
||||
|
||||
@@ -39,8 +40,13 @@ public class DesensitizeValueFilter implements ValueFilter {
|
||||
if (config == null) {
|
||||
return value;
|
||||
}
|
||||
// 脱敏
|
||||
return Desensitizes.mix(Objects1.toString(value), config.keepStart(), config.keepEnd(), config.replacer());
|
||||
if (config.toEmpty()) {
|
||||
// 设置为空
|
||||
return Const.EMPTY;
|
||||
} else {
|
||||
// 脱敏
|
||||
return Desensitizes.mix(Objects1.toString(value), config.keepStart(), config.keepEnd(), config.replacer());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
|
||||
import com.orion.lang.constant.Const;
|
||||
import com.orion.lang.utils.Desensitizes;
|
||||
import com.orion.lang.utils.Objects1;
|
||||
import com.orion.ops.framework.desensitize.core.annotation.Desensitize;
|
||||
@@ -24,6 +25,10 @@ import java.util.Objects;
|
||||
*/
|
||||
public class DesensitizeJsonSerializer extends JsonSerializer<Object> implements ContextualSerializer {
|
||||
|
||||
/**
|
||||
* 这里是线程安全的
|
||||
* 同一个字段使用同一个 serializer 所以不需要使用 TheadLocal
|
||||
*/
|
||||
private Desensitize desensitize;
|
||||
|
||||
@Override
|
||||
@@ -43,9 +48,14 @@ public class DesensitizeJsonSerializer extends JsonSerializer<Object> implements
|
||||
gen.writeNull();
|
||||
return;
|
||||
}
|
||||
// 脱敏
|
||||
String mix = Desensitizes.mix(Objects1.toString(value), desensitize.keepStart(), desensitize.keepEnd(), desensitize.replacer());
|
||||
gen.writeString(mix);
|
||||
if (desensitize.toEmpty()) {
|
||||
// 设置为空
|
||||
gen.writeString(Const.EMPTY);
|
||||
} else {
|
||||
// 脱敏
|
||||
String mix = Desensitizes.mix(Objects1.toString(value), desensitize.keepStart(), desensitize.keepEnd(), desensitize.replacer());
|
||||
gen.writeString(mix);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
package com.orion.ops.module.infra.controller;
|
||||
|
||||
import com.orion.lang.define.wrapper.HttpWrapper;
|
||||
import com.orion.ops.framework.biz.operator.log.core.annotation.OperatorLog;
|
||||
import com.orion.ops.framework.log.core.annotation.IgnoreLog;
|
||||
import com.orion.ops.framework.log.core.enums.IgnoreLogMode;
|
||||
import com.orion.ops.framework.security.core.utils.SecurityUtils;
|
||||
import com.orion.ops.framework.web.core.annotation.RestWrapper;
|
||||
import com.orion.ops.module.infra.define.operator.AuthenticationOperatorType;
|
||||
import com.orion.ops.module.infra.entity.request.user.UserLoginRequest;
|
||||
import com.orion.ops.module.infra.entity.request.user.UserResetPasswordRequest;
|
||||
import com.orion.ops.module.infra.entity.vo.UserLoginVO;
|
||||
@@ -42,15 +44,16 @@ public class AuthenticationController {
|
||||
@Resource
|
||||
private SystemUserService systemUserService;
|
||||
|
||||
@OperatorLog(AuthenticationOperatorType.LOGIN)
|
||||
@PermitAll
|
||||
@Operation(summary = "登陆")
|
||||
@PostMapping("/login")
|
||||
public UserLoginVO login(@Validated @RequestBody UserLoginRequest request,
|
||||
HttpServletRequest servletRequest) {
|
||||
String token = authenticationService.login(request, servletRequest);
|
||||
return UserLoginVO.builder().token(token).build();
|
||||
return authenticationService.login(request, servletRequest);
|
||||
}
|
||||
|
||||
@OperatorLog(AuthenticationOperatorType.LOGOUT)
|
||||
@PermitAll
|
||||
@IgnoreLog(IgnoreLogMode.RET)
|
||||
@Operation(summary = "登出")
|
||||
@@ -60,6 +63,7 @@ public class AuthenticationController {
|
||||
return HttpWrapper.ok();
|
||||
}
|
||||
|
||||
@OperatorLog(AuthenticationOperatorType.UPDATE_PASSWORD)
|
||||
@Operation(summary = "修改密码")
|
||||
@PutMapping("/update-password")
|
||||
public HttpWrapper<?> updatePassword(@Validated @RequestBody UserResetPasswordRequest request) {
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.orion.ops.module.infra.define.operator;
|
||||
|
||||
import com.orion.ops.framework.biz.operator.log.core.model.OperatorType;
|
||||
|
||||
import static com.orion.ops.framework.biz.operator.log.core.holder.OperatorTypeHolder.set;
|
||||
|
||||
/**
|
||||
* 认证服务 操作日志类型
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2023-10-10 19:06
|
||||
*/
|
||||
public class AuthenticationOperatorType {
|
||||
|
||||
private static final String MODULE = "infra:authentication";
|
||||
|
||||
public static final String LOGIN = "authentication:login";
|
||||
|
||||
public static final String LOGOUT = "authentication:logout";
|
||||
|
||||
public static final String UPDATE_PASSWORD = "authentication:update-password";
|
||||
|
||||
public static void init() {
|
||||
set(new OperatorType(MODULE, LOGIN, "登陆系统"));
|
||||
set(new OperatorType(MODULE, LOGOUT, "登出系统"));
|
||||
set(new OperatorType(MODULE, UPDATE_PASSWORD, "修改密码"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -36,6 +36,10 @@ public class OperatorLogDO extends BaseDO {
|
||||
@TableField("user_id")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "用户名")
|
||||
@TableField("username")
|
||||
private String username;
|
||||
|
||||
@Schema(description = "traceId")
|
||||
@TableField("trace_id")
|
||||
private String traceId;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.orion.ops.module.infra.entity.request.user;
|
||||
|
||||
import com.orion.ops.framework.desensitize.core.annotation.Desensitize;
|
||||
import com.orion.ops.framework.desensitize.core.annotation.DesensitizeObject;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -13,6 +15,7 @@ import javax.validation.constraints.NotEmpty;
|
||||
* @since 2023/7/13 22:16
|
||||
*/
|
||||
@Data
|
||||
@DesensitizeObject
|
||||
@Schema(name = "UserLoginRequest", description = "登陆请求")
|
||||
public class UserLoginRequest {
|
||||
|
||||
@@ -20,6 +23,7 @@ public class UserLoginRequest {
|
||||
@Schema(description = "用户名")
|
||||
private String username;
|
||||
|
||||
@Desensitize(toEmpty = true)
|
||||
@NotEmpty
|
||||
@Schema(description = "密码")
|
||||
private String password;
|
||||
|
||||
@@ -31,6 +31,9 @@ public class OperatorLogVO implements Serializable {
|
||||
@Schema(description = "用户id")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "用户名")
|
||||
private String username;
|
||||
|
||||
@Schema(description = "traceId")
|
||||
private String traceId;
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.orion.ops.module.infra.runner;
|
||||
|
||||
import com.orion.ops.module.infra.define.operator.AuthenticationOperatorType;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 操作类型 初始化
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2023/10/10 18:03
|
||||
*/
|
||||
@Component
|
||||
public class InfraOperatorTypeRunner implements CommandLineRunner {
|
||||
|
||||
@Override
|
||||
public void run(String... args) {
|
||||
AuthenticationOperatorType.init();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.orion.ops.module.infra.service;
|
||||
import com.orion.ops.framework.common.security.LoginUser;
|
||||
import com.orion.ops.module.infra.entity.dto.LoginTokenDTO;
|
||||
import com.orion.ops.module.infra.entity.request.user.UserLoginRequest;
|
||||
import com.orion.ops.module.infra.entity.vo.UserLoginVO;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@@ -30,9 +31,9 @@ public interface AuthenticationService {
|
||||
*
|
||||
* @param request request
|
||||
* @param servletRequest servletRequest
|
||||
* @return token
|
||||
* @return login
|
||||
*/
|
||||
String login(UserLoginRequest request, HttpServletRequest servletRequest);
|
||||
UserLoginVO login(UserLoginRequest request, HttpServletRequest servletRequest);
|
||||
|
||||
/**
|
||||
* 登出
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.orion.lang.define.wrapper.Pair;
|
||||
import com.orion.lang.utils.Exceptions;
|
||||
import com.orion.lang.utils.collect.Lists;
|
||||
import com.orion.lang.utils.crypto.Signatures;
|
||||
import com.orion.ops.framework.biz.operator.log.core.uitls.OperatorLogs;
|
||||
import com.orion.ops.framework.common.constant.Const;
|
||||
import com.orion.ops.framework.common.constant.ErrorMessage;
|
||||
import com.orion.ops.framework.common.security.LoginUser;
|
||||
@@ -23,6 +24,7 @@ import com.orion.ops.module.infra.entity.domain.SystemRoleDO;
|
||||
import com.orion.ops.module.infra.entity.domain.SystemUserDO;
|
||||
import com.orion.ops.module.infra.entity.dto.LoginTokenDTO;
|
||||
import com.orion.ops.module.infra.entity.request.user.UserLoginRequest;
|
||||
import com.orion.ops.module.infra.entity.vo.UserLoginVO;
|
||||
import com.orion.ops.module.infra.enums.LoginTokenStatusEnum;
|
||||
import com.orion.ops.module.infra.enums.UserStatusEnum;
|
||||
import com.orion.ops.module.infra.service.AuthenticationService;
|
||||
@@ -62,13 +64,15 @@ public class AuthenticationServiceImpl implements AuthenticationService {
|
||||
private RedisTemplate<String, String> redisTemplate;
|
||||
|
||||
@Override
|
||||
public String login(UserLoginRequest request, HttpServletRequest servletRequest) {
|
||||
public UserLoginVO login(UserLoginRequest request, HttpServletRequest servletRequest) {
|
||||
// 登陆前检查
|
||||
this.preCheckLogin(request);
|
||||
// 获取登陆用户
|
||||
LambdaQueryWrapper<SystemUserDO> wrapper = systemUserDAO.wrapper()
|
||||
.eq(SystemUserDO::getUsername, request.getUsername());
|
||||
SystemUserDO user = systemUserDAO.of(wrapper).getOne();
|
||||
// 设置日志上下文
|
||||
OperatorLogs.setUser(SystemUserConvert.MAPPER.toLoginUser(user));
|
||||
// 检查密码
|
||||
boolean passwordCorrect = this.checkPassword(request, user);
|
||||
Valid.isTrue(passwordCorrect, ErrorMessage.USERNAME_PASSWORD_ERROR);
|
||||
@@ -90,7 +94,10 @@ public class AuthenticationServiceImpl implements AuthenticationService {
|
||||
this.invalidOtherDeviceToken(user.getId(), current, remoteAddr, location);
|
||||
}
|
||||
// 生成 loginToken
|
||||
return this.generatorLoginToken(user, current, remoteAddr, location);
|
||||
String token = this.generatorLoginToken(user, current, remoteAddr, location);
|
||||
return UserLoginVO.builder()
|
||||
.token(token)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -63,7 +63,7 @@ public class SystemUserServiceImpl implements SystemUserService {
|
||||
public Long createSystemUser(SystemUserCreateRequest request) {
|
||||
// 转换
|
||||
SystemUserDO record = SystemUserConvert.MAPPER.to(request);
|
||||
// 查询用户名称是否存在
|
||||
// 查询用户名是否存在
|
||||
this.checkUsernamePresent(record);
|
||||
// 查询花名是否存在
|
||||
this.checkNicknamePresent(record);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<resultMap id="BaseResultMap" type="com.orion.ops.module.infra.entity.domain.OperatorLogDO">
|
||||
<id column="id" property="id"/>
|
||||
<result column="user_id" property="userId"/>
|
||||
<result column="username" property="username"/>
|
||||
<result column="trace_id" property="traceId"/>
|
||||
<result column="address" property="address"/>
|
||||
<result column="location" property="location"/>
|
||||
@@ -25,7 +26,7 @@
|
||||
|
||||
<!-- 通用查询结果列 -->
|
||||
<sql id="Base_Column_List">
|
||||
id, user_id, trace_id, address, location, user_agent, module, type, log_info, extra, result, error_message, return_value, duration, start_time, end_time, create_time
|
||||
id, user_id, username, trace_id, address, location, user_agent, module, type, log_info, extra, result, error_message, return_value, duration, start_time, end_time, create_time
|
||||
</sql>
|
||||
|
||||
</mapper>
|
||||
|
||||
Reference in New Issue
Block a user