This commit is contained in:
s2042968 2025-02-14 09:20:49 +08:00
commit ff9b219ef3
12 changed files with 225 additions and 25 deletions

View File

@ -1,11 +1,13 @@
package com.electromagnetic.industry.software.manage.aop;
import cn.hutool.json.JSONUtil;
import com.electromagnetic.industry.software.common.resp.ElectromagneticResult;
import com.electromagnetic.industry.software.common.util.UserThreadLocal;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.ResponseFacade;
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.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
@ -13,8 +15,8 @@ import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
@Aspect
@Component
@ -29,30 +31,34 @@ public class ServiceAspect {
String methodInfo = jp.getTarget().getClass().getSimpleName() + "."
+ jp.getSignature().getName();
Object[] args = jp.getArgs();
String[] argNames = ((MethodSignature)jp.getSignature()).getParameterNames();
String paramInfo = "";
if (args != null && args.length > 0) {
if (args[0] != null && args[0].getClass() != ResponseFacade.class) {
try {
List<Object> list = new ArrayList<>();
for (Object obj : jp.getArgs()) {
if (obj instanceof ServletResponse) {
log.info("参数中有response");
} else if (obj instanceof ServletRequest) {
log.info("参数中有request");
} else if (obj instanceof MultipartFile) {
//文件不输出
MultipartFile obj1 = (MultipartFile) obj;
log.info("参数中文件;文件名:{},文件大小:{}", obj1.getName(), obj1.getSize());
break;
} else {
list.add(obj);
}
Map<String, Object> map = new HashMap<>();
try {
for (int i = 0; i < args.length; i++) {
String name = argNames[i];
Object value = args[i];
if (value instanceof ServletRequest) {
log.info("参数中有request");
map.put(name, "request");
} else if (value instanceof ServletResponse) {
log.info("参数中有response");
map.put(name, "response");
} else if (value instanceof MultipartFile) {
MultipartFile file = (MultipartFile) value;
Map<String, Object> pars = new HashMap<>();
pars.put("fileName", file.getOriginalFilename());
pars.put("fileSize", file.getSize());
map.put("file", pars);
} else {
map.put(name, value);
}
paramInfo = JSONUtil.toJsonStr(list);
} catch (Exception e) {
log.warn("切面异常--->{}", e.getMessage());
}
} catch (Exception e) {
log.warn("切面异常--->{}", e.getMessage(), e);
} finally {
paramInfo = JSONUtil.toJsonStr(map);
}
}
log.info("请求接口开始:{},参数:{}", methodInfo, paramInfo);
@ -63,6 +69,8 @@ public class ServiceAspect {
if (rvt instanceof ResponseEntity) {
return rvt;
}
UserThreadLocal.setRes((ElectromagneticResult)rvt);
UserThreadLocal.setReqArgs(paramInfo);
String returnInfo = JSONUtil.toJsonStr(rvt);
log.info("请求接口结束:{},返回参数:{},接口耗时:{}", methodInfo, returnInfo, (System.currentTimeMillis() - startTime) + "毫秒");
stopwatch.stop();

View File

@ -1,16 +1,24 @@
package com.electromagnetic.industry.software.manage.config;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.SystemClock;
import com.electromagnetic.industry.software.common.annotations.UserOperation;
import com.electromagnetic.industry.software.common.cons.UserConstants;
import com.electromagnetic.industry.software.common.enums.AdminTypeEnum;
import com.electromagnetic.industry.software.common.pojo.UserLoginInfo;
import com.electromagnetic.industry.software.common.resp.ElectromagneticResult;
import com.electromagnetic.industry.software.common.util.IdWorker;
import com.electromagnetic.industry.software.common.util.TokenUtil;
import com.electromagnetic.industry.software.common.util.UserThreadLocal;
import com.electromagnetic.industry.software.manage.mapper.TokenMapper;
import com.electromagnetic.industry.software.manage.mapper.UserAccessLogMapper;
import com.electromagnetic.industry.software.manage.mapper.UserMapper;
import com.electromagnetic.industry.software.manage.pojo.models.Token;
import com.electromagnetic.industry.software.manage.pojo.models.UserAccessLog;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
@ -26,8 +34,12 @@ public class LoginInterceptor implements HandlerInterceptor {
@Resource
private TokenMapper tokenMapper;
@Resource
private UserAccessLogMapper userAccessLogMapper;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
request.getSession().setAttribute("accessStartTime", System.currentTimeMillis());
// 首先校验token
boolean isTokenValid = checkToken(request, response);
if (!isTokenValid) {
@ -86,6 +98,31 @@ public class LoginInterceptor implements HandlerInterceptor {
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
long accessStartTime = (long)request.getSession().getAttribute("accessStartTime");
ElectromagneticResult<?> result = UserThreadLocal.getResult();
String reqArgs = UserThreadLocal.getReqArgs();
long accessEndTime = System.currentTimeMillis();
UserOperation userOperation = ((HandlerMethod) handler).getMethod().getAnnotation(UserOperation.class);
UserAccessLog userAccessLog = UserAccessLog.builder()
.id(IdWorker.getSnowFlakeIdString())
.userId(UserThreadLocal.getUserId())
.accessStartTime(DateUtil.date(accessStartTime))
.accessEndTime(DateUtil.date(accessEndTime))
.accessDuration(accessEndTime - accessStartTime)
.action(userOperation.value())
.requestUrl(request.getRequestURL().toString())
.reqArgs(reqArgs)
.remoteAddr(request.getRemoteAddr())
.accessSuccess(true)
.createTime(new Date())
.build();
if (!result.getSuccess()) {
userAccessLog.setAccessSuccess(false);
userAccessLog.setFailureReason(result.getErrorMessage());
}
// TODO 如果是下载的文件那么返回的是ResponseEntity而不是ElectromagneticResult
userAccessLogMapper.insert(userAccessLog);
UserThreadLocal.remove();
}

View File

@ -132,4 +132,10 @@ public class EdFileInfoController {
public ElectromagneticResult<?> queryChildFolder(@RequestParam String parentId) {
return edFileInfoService.queryChildFolder(parentId);
}
@RequiredPermission(value = FilePermission.VIEW)
@RequestMapping(value = "preview", method = RequestMethod.GET)
public ResponseEntity<InputStreamResource> preview(@RequestParam String id, HttpServletResponse response) {
return edFileInfoService.preview(id, response);
}
}

View File

@ -0,0 +1,9 @@
package com.electromagnetic.industry.software.manage.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.electromagnetic.industry.software.manage.pojo.models.UserAccessLog;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserAccessLogMapper extends BaseMapper<UserAccessLog> {
}

View File

@ -0,0 +1,37 @@
package com.electromagnetic.industry.software.manage.pojo.models;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Builder;
import lombok.Data;
import java.util.Date;
@Data
@Builder
@TableName("user_access_log")
public class UserAccessLog {
private String id;
private String userId;
private Date accessStartTime;
private Date accessEndTime;
private Long accessDuration;
private String action;
private String requestUrl;
private String reqArgs;
private String remoteAddr;
private Boolean accessSuccess;
private String failureReason;
private Date createTime;
}

View File

@ -164,4 +164,11 @@ public interface EdFileInfoService {
* @return
*/
ElectromagneticResult<?> queryChildFolder(String parentId);
/**
* 文件预览
* @param id
* @param response
*/
ResponseEntity<InputStreamResource> preview(String id, HttpServletResponse response);
}

View File

@ -75,12 +75,14 @@ public class EdFileInfoServiceImpl extends ServiceImpl<EdFileInfoMapper, EdFileI
private String downloadDataDir = "";
private String uploadDataDir = "";
private String tmpDir = "";
@PostConstruct
public void init() {
String osName = System.getProperty("os.name").toLowerCase();
uploadDataDir = osName.startsWith("win") ? environment.getProperty("data.upload.windows.tmp.path") : environment.getProperty("data.upload.linux.tmp.path");
downloadDataDir = osName.startsWith("win") ? environment.getProperty("data.download.windows.tmp.path") : environment.getProperty("data.download.linux.tmp.path");
tmpDir = osName.startsWith("win") ? environment.getProperty("data.windows.tmp.path") : environment.getProperty("data.linux.tmp.path");
}
/**
@ -1195,4 +1197,44 @@ public class EdFileInfoServiceImpl extends ServiceImpl<EdFileInfoMapper, EdFileI
return ElectromagneticResultUtil.success(res);
}
/**
* 文件预览
*
* @param id
* @param response
*/
@Override
public ResponseEntity<InputStreamResource> preview(String id, HttpServletResponse response) {
try {
EdFileInfo fileInfo = this.baseMapper.selectById(id);
Assert.isTrue(Objects.nonNull(fileInfo), "文件不存在");
String fileSysPath = commonService.getFileSysPath(fileInfo.getFilePath());
EleCommonUtil.decryptFile(fileSysPath, SecureUtil.aes(FILE_SEC_PASSWD.getBytes()));
if (Arrays.asList("doc", "docx").contains(fileInfo.getFileType())) {
String pdfTmpPath = tmpDir + File.separator + fileInfo.getFileName() + "_" + IdUtil.fastSimpleUUID() + ".pdf";
OfficeFileUtil.doc2pdf(fileSysPath, pdfTmpPath);
fileSysPath = pdfTmpPath;
}
FileSystemResource fileSystemResource = new FileSystemResource(fileSysPath);
String fileName = fileSystemResource.getFilename();
HttpHeaders headers = new HttpHeaders();
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
headers.add("Pragma", "no-cache");
headers.add("Expires", "0");
fileName = Base64.encode(fileName.substring(0, fileName.lastIndexOf(".")));
response.setHeader("content-disposition", "attachment;filename=" + fileName);
// 构建响应实体(可以返回<byte[]或Resource返回类型取决body入参类型)
return ResponseEntity
.ok()
.headers(headers)
.contentLength(fileSystemResource.contentLength())
.contentType(MediaType.parseMediaType("application/octet-stream;charset=UTF-8"))
.body(new InputStreamResource(fileSystemResource.getInputStream()));
} catch (Exception e) {
String info = StrFormatter.format("文件预览错误文件id是--->{},错误信息--->{}", id,e.getMessage());
log.error(info, e);
throw new BizException(info);
}
}
}

View File

@ -17,10 +17,12 @@ server.port=12396
data.windows.path=D:/tmp/szsd/data/eleData/dev/project/
data.upload.windows.tmp.path=D:/tmp/szsd/data/eleData/dev/upload/
data.download.windows.tmp.path=D:/tmp/szsd/data/eleData/dev/download/
data.windows.tmp.path=D:/szsd/data/eleData/dev/tmp
data.linux.path=/szsd/data/eleData/dev/project/
data.upload.linux.tmp.path=/szsd/data/eleData/dev/upload/
data.download.linux.tmp.path=/szsd/data/eleData/dev/download/
data.linux.tmp.path=/szsd/data/eleData/dev/tmp
prj.folder.max.length=6

View File

@ -0,0 +1,11 @@
package com.electromagnetic.industry.software.common.annotations;
import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.PARAMETER})
public @interface UserOperation {
String value() default "";
}

View File

@ -1,5 +1,6 @@
package com.electromagnetic.industry.software.common.pojo;
import com.electromagnetic.industry.software.common.resp.ElectromagneticResult;
import lombok.Data;
@Data
@ -34,4 +35,14 @@ public class UserLoginInfo {
* 管理员类型
*/
private String adminType;
/**
* 返回值
*/
private ElectromagneticResult result;
/**
* 访问请求的参数
*/
private String reqArgs;
}

View File

@ -57,13 +57,25 @@ public final class EleCommonUtil {
return now.format(formatter);
}
public static void decryptFile(String filePath, AES aes) {
handleFile(filePath, aes, false);
}
public static void encryptFile(String filePath, AES aes) {
handleFile(filePath, aes, true);
}
private static void handleFile(String filePath, AES aes, boolean encrypt) {
String tmpPath = filePath + ".tmp";
try (
InputStream inputStream = Files.newInputStream(Paths.get(filePath));
OutputStream outputStream = Files.newOutputStream(Paths.get(tmpPath));
) {
aes.encrypt(inputStream, outputStream, true);
if (encrypt) {
aes.encrypt(inputStream, outputStream, true);
} else {
aes.decrypt(inputStream, outputStream, true);
}
} catch (Exception e) {
String info = "文件加密失败";
log.error(info, e);

View File

@ -2,12 +2,13 @@ package com.electromagnetic.industry.software.common.util;
import com.electromagnetic.industry.software.common.pojo.UserLoginInfo;
import com.electromagnetic.industry.software.common.resp.ElectromagneticResult;
public class UserThreadLocal {
/**
* 存储用户信息
*/
private static ThreadLocal<UserLoginInfo> userThread = new ThreadLocal<>();
private static final ThreadLocal<UserLoginInfo> userThread = new ThreadLocal<>();
public static void set(UserLoginInfo userLoginInfo) {
userThread.set(userLoginInfo);
@ -32,4 +33,21 @@ public class UserThreadLocal {
public static void remove() {
userThread.remove();
}
public static void setRes(ElectromagneticResult result) {
userThread.get().setResult(result);
}
public static ElectromagneticResult getResult() {
return userThread.get().getResult();
}
public static void setReqArgs(String args) {
userThread.get().setReqArgs(args);
}
public static String getReqArgs() {
return userThread.get().getReqArgs();
}
}