diff --git a/framework/gateway/src/main/java/io/metersphere/gateway/config/LogConfig.java b/framework/gateway/src/main/java/io/metersphere/gateway/config/LogConfig.java new file mode 100644 index 0000000000..7bf058bdbb --- /dev/null +++ b/framework/gateway/src/main/java/io/metersphere/gateway/config/LogConfig.java @@ -0,0 +1,14 @@ +package io.metersphere.gateway.config; + +import io.metersphere.log.service.OperatingLogService; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class LogConfig { + + @Bean + public OperatingLogService operatingLogService() { + return new OperatingLogService(); + } +} diff --git a/framework/gateway/src/main/java/io/metersphere/gateway/controller/LdapController.java b/framework/gateway/src/main/java/io/metersphere/gateway/controller/LdapController.java index b6f739af7c..4a47b5dcc1 100644 --- a/framework/gateway/src/main/java/io/metersphere/gateway/controller/LdapController.java +++ b/framework/gateway/src/main/java/io/metersphere/gateway/controller/LdapController.java @@ -4,7 +4,7 @@ import io.metersphere.commons.constants.OperLogConstants; import io.metersphere.commons.constants.OperLogModule; import io.metersphere.controller.handler.ResultHolder; import io.metersphere.gateway.service.LdapService; -import io.metersphere.log.annotation.MsAuditLog; +import io.metersphere.gateway.log.annotation.MsAuditLog; import io.metersphere.request.LoginRequest; import org.springframework.web.bind.annotation.*; import org.springframework.web.server.WebSession; diff --git a/framework/gateway/src/main/java/io/metersphere/gateway/controller/LoginController.java b/framework/gateway/src/main/java/io/metersphere/gateway/controller/LoginController.java index b0734fa9be..03a3431d87 100644 --- a/framework/gateway/src/main/java/io/metersphere/gateway/controller/LoginController.java +++ b/framework/gateway/src/main/java/io/metersphere/gateway/controller/LoginController.java @@ -1,6 +1,8 @@ package io.metersphere.gateway.controller; import io.metersphere.base.domain.User; +import io.metersphere.commons.constants.OperLogConstants; +import io.metersphere.commons.constants.OperLogModule; import io.metersphere.commons.constants.SessionConstants; import io.metersphere.commons.utils.RsaKey; import io.metersphere.commons.utils.RsaUtil; @@ -10,6 +12,7 @@ import io.metersphere.gateway.service.AuthSourceService; import io.metersphere.gateway.service.BaseDisplayService; import io.metersphere.gateway.service.SystemParameterService; import io.metersphere.gateway.service.UserLoginService; +import io.metersphere.gateway.log.annotation.MsAuditLog; import io.metersphere.request.LoginRequest; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; @@ -68,6 +71,7 @@ public class LoginController { } @PostMapping(value = "/signin") + @MsAuditLog(module = OperLogModule.AUTH_TITLE, type = OperLogConstants.LOGIN, title = "登录") public Mono login(@RequestBody LoginRequest request, WebSession session, Locale locale) { return Mono.defer(() -> userLoginService.login(request, session, locale).map(Mono::just).orElseGet(Mono::empty)) .subscribeOn(Schedulers.boundedElastic()) diff --git a/framework/gateway/src/main/java/io/metersphere/gateway/controller/SSOController.java b/framework/gateway/src/main/java/io/metersphere/gateway/controller/SSOController.java index e4f96e8a7f..1ca0b61298 100644 --- a/framework/gateway/src/main/java/io/metersphere/gateway/controller/SSOController.java +++ b/framework/gateway/src/main/java/io/metersphere/gateway/controller/SSOController.java @@ -4,13 +4,15 @@ import io.metersphere.commons.constants.OperLogConstants; import io.metersphere.commons.constants.OperLogModule; import io.metersphere.commons.user.SessionUser; import io.metersphere.commons.utils.CodingUtil; +import io.metersphere.gateway.log.annotation.MsAuditLog; import io.metersphere.gateway.service.SSOService; -import io.metersphere.log.annotation.MsAuditLog; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.reactive.result.view.Rendering; import org.springframework.web.server.WebSession; -import reactor.core.publisher.Mono; import javax.annotation.Resource; import java.util.Locale; diff --git a/framework/gateway/src/main/java/io/metersphere/gateway/log/annotation/MsAuditLog.java b/framework/gateway/src/main/java/io/metersphere/gateway/log/annotation/MsAuditLog.java new file mode 100644 index 0000000000..83a06eedc3 --- /dev/null +++ b/framework/gateway/src/main/java/io/metersphere/gateway/log/annotation/MsAuditLog.java @@ -0,0 +1,70 @@ +package io.metersphere.gateway.log.annotation; + +import io.metersphere.commons.constants.OperLogConstants; + +import java.lang.annotation.*; + +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +/** + * MsAuditLog class + * @author mr.zhao + * @date 2021/05/06 + */ +public @interface MsAuditLog { + /** + * 功能模块 + * + * @return + */ + String module(); + + /** + * 项目 + * + * @return + */ + String project() default ""; + + /** + * 操作类型 + * + * @return + */ + OperLogConstants type() default OperLogConstants.OTHER; + + /** + * 标题 + */ + String title() default ""; + + /** + * 资源ID + */ + String sourceId() default ""; + + + /** + * 操作内容 + * + * @return + */ + String content() default ""; + + /** + * 操作前触发内容 + * + * @return + */ + String beforeEvent() default ""; + + /** + * 传入执行类 + * + * @return + */ + Class[] msClass() default {}; + + +} diff --git a/framework/gateway/src/main/java/io/metersphere/gateway/log/aspect/MsLogAspect.java b/framework/gateway/src/main/java/io/metersphere/gateway/log/aspect/MsLogAspect.java new file mode 100644 index 0000000000..0933e4c778 --- /dev/null +++ b/framework/gateway/src/main/java/io/metersphere/gateway/log/aspect/MsLogAspect.java @@ -0,0 +1,129 @@ +package io.metersphere.gateway.log.aspect; + + +import io.metersphere.base.domain.OperatingLogWithBLOBs; +import io.metersphere.commons.utils.LogUtil; +import io.metersphere.gateway.log.annotation.MsAuditLog; +import io.metersphere.log.service.OperatingLogService; +import io.metersphere.request.LoginRequest; +import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.core.LocalVariableTableParameterNameDiscoverer; +import org.springframework.expression.EvaluationContext; +import org.springframework.expression.Expression; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.lang.reflect.Method; +import java.util.UUID; + +/** + * 系统日志:切面处理类 + */ +@Aspect +@Component +public class MsLogAspect { + /** + * 解析spel表达式 + */ + ExpressionParser parser = new SpelExpressionParser(); + /** + * 将方法参数纳入Spring管理 + */ + LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer(); + @Resource + private OperatingLogService operatingLogService; + + /** + * 定义切点 @Pointcut 在注解的位置切入代码 + */ + @Pointcut("@annotation(io.metersphere.gateway.log.annotation.MsAuditLog)") + public void logPointCut() { + } + + + /** + * 切面 配置通知 + */ + @AfterReturning("logPointCut()") + public void saveLog(JoinPoint joinPoint) { + try { + + //从切面织入点处通过反射机制获取织入点处的方法 + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + //获取切入点所在的方法 + Method method = signature.getMethod(); + //获取参数对象数组 + Object[] args = joinPoint.getArgs(); + + //获取操作 + MsAuditLog msLog = method.getAnnotation(MsAuditLog.class); + if (msLog != null) { + //保存日志 + OperatingLogWithBLOBs msOperLog = new OperatingLogWithBLOBs(); + + //保存获取的操作 + msOperLog.setId(UUID.randomUUID().toString()); + // 操作类型 + msOperLog.setOperType(msLog.type().name()); + // 项目ID + msOperLog.setProjectId(msLog.project()); + + String module = msLog.module(); + msOperLog.setOperModule(StringUtils.isNotEmpty(module) ? module : msLog.module()); + //获取方法参数名 + String[] params = discoverer.getParameterNames(method); + //将参数纳入Spring管理 + EvaluationContext context = new StandardEvaluationContext(); + for (int len = 0; len < params.length; len++) { + context.setVariable(params[len], args[len]); + } + + // 标题 + if (StringUtils.isNotEmpty(msLog.title())) { + String title = msLog.title(); + try { + Expression titleExp = parser.parseExpression(title); + title = titleExp.getValue(context, String.class); + msOperLog.setOperTitle(title); + } catch (Exception e) { + msOperLog.setOperTitle(title); + } + } + + //获取请求的类名 + String className = joinPoint.getTarget().getClass().getName(); + //获取请求的方法名 + String methodName = method.getName(); + msOperLog.setOperMethod(className + "." + methodName); + + msOperLog.setOperTime(System.currentTimeMillis()); + + for (Object arg : args) { + if (arg instanceof LoginRequest) { + //获取用户名 + msOperLog.setOperUser(((LoginRequest) arg).getUsername()); + break; + } + } + + if (StringUtils.isNotEmpty(msOperLog.getOperTitle()) && msOperLog.getOperTitle().length() > 6000) { + msOperLog.setOperTitle(msOperLog.getOperTitle().substring(0, 5999)); + } +// msOperLog.setOperPath(path); + operatingLogService.create(msOperLog, msOperLog.getSourceId()); + } + } catch (Exception e) { + LogUtil.error("操作日志写入异常:" + joinPoint.getSignature()); + } + } + + +}