diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/common/util/PreviewFileIdEncryptUtil.java b/hz-pm-api/src/main/java/com/hz/pm/api/common/util/PreviewFileIdEncryptUtil.java new file mode 100644 index 0000000..435c52c --- /dev/null +++ b/hz-pm-api/src/main/java/com/hz/pm/api/common/util/PreviewFileIdEncryptUtil.java @@ -0,0 +1,32 @@ +package com.hz.pm.api.common.util; + +import cn.hutool.core.codec.Base64; +import cn.hutool.crypto.SecureUtil; +import cn.hutool.crypto.symmetric.AES; + +/** + *

+ * PreviewFileIdEncryptUtil + *

+ * + * @author WendyYang + * @since 13:36 2024/11/19 + */ +public class PreviewFileIdEncryptUtil { + + private PreviewFileIdEncryptUtil() { + } + + private static final String KEY_BASE64 = "ffbTIYYplRaDcNnrP3dm99s8jCGls4bBqJPnFUo44ik="; + + public static String encryptFileId(String fileId) { + AES aes = SecureUtil.aes(Base64.decode(KEY_BASE64)); + return aes.encryptHex(fileId); + } + + public static String decryptFileId(String fileId) { + AES aes = SecureUtil.aes(Base64.decode(KEY_BASE64)); + return aes.decryptStr(fileId); + } + +} diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/external/FilePreviewClient.java b/hz-pm-api/src/main/java/com/hz/pm/api/external/FilePreviewClient.java index 57fd9ad..88f36c5 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/external/FilePreviewClient.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/external/FilePreviewClient.java @@ -1,6 +1,10 @@ package com.hz.pm.api.external; +import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.NumberUtil; +import com.hz.pm.api.common.enumeration.FileOrigin; +import com.hz.pm.api.common.util.PreviewFileIdEncryptUtil; +import com.hz.pm.api.external.model.PreviewFileIdBO; import com.hz.pm.api.external.model.dto.MhFileInfoDTO; import com.hz.pm.api.meeting.entity.config.WebProps; import com.ningdatech.basic.exception.BizException; @@ -14,6 +18,7 @@ import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.time.Duration; import java.util.List; /** @@ -41,9 +46,6 @@ public class FilePreviewClient { private static final String FILE_DOWN_NO_AUTH_URL = "/api/v1/file/preview/anonymous/down/"; - private static final String MH_DOWN_FILE_URL = "/api/v1/mh/anonymous/file/download/"; - - //================================================================================================================== private static final String PREVIEW_PATH_FMT = "%s/public/risen/core/resrc/view/pdf_view.html.do?strMap.remote_url=%s&strMap.ext=%s"; @@ -52,11 +54,14 @@ public class FilePreviewClient { String serverName = request.getServerName(); log.info("serverName:{}", serverName); StringBuilder fileDownUrl = new StringBuilder(); + String filePreviewUrlHost; if (serverName.contains("weixin") || serverName.contains("10.54.38.13")) { // 浙政钉访问需要转换为互联网可访问的地址 fileDownUrl.append(WebProps.zzdApiUrl); + filePreviewUrlHost = mhFilePreviewPublicUrl; } else { fileDownUrl.append(WebProps.apiUrl); + filePreviewUrlHost = mhFilePreviewPrivateUrl; } String fileSuffix; // 信产文件ID为字符串、当前系统文件ID为数字 @@ -64,18 +69,55 @@ public class FilePreviewClient { List fileInfos = mhFileClient.listFileInfo(fileId); MhFileInfoDTO mhFileInfo = fileInfos.get(0); fileSuffix = mhFileInfo.getFileSuffix(); - fileDownUrl.append(MH_DOWN_FILE_URL).append(fileId); + String tmpFileId = generateFileId(fileId, FileOrigin.MH); + fileDownUrl.append(FILE_DOWN_NO_AUTH_URL).append(tmpFileId); } else { - fileDownUrl.append(FILE_DOWN_NO_AUTH_URL).append(fileId); + String tmpFileId = generateFileId(fileId, FileOrigin.OSS); + fileDownUrl.append(FILE_DOWN_NO_AUTH_URL).append(tmpFileId); File file = fileService.getById(fileId); fileSuffix = file.getSuffix(); } - return String.format(PREVIEW_PATH_FMT, mhFilePreviewPrivateUrl, fileDownUrl, fileSuffix); + return String.format(PREVIEW_PATH_FMT, filePreviewUrlHost, fileDownUrl, fileSuffix); + } + + private static String generateFileId(String fileId, FileOrigin oss) { + PreviewFileIdBO previewFileId = PreviewFileIdBO.builder() + // 默认过期时间6小时 + .expireTime(System.currentTimeMillis() + Duration.ofHours(6).toMillis()) + .fileId(fileId) + .fileOrigin(oss) + .build(); + return PreviewFileIdEncryptUtil.encryptFileId(previewFileId.concat()); + } + + private static PreviewFileIdBO parseFileId(String fileId) { + String decryptFileId = PreviewFileIdEncryptUtil.decryptFileId(fileId); + String[] split = decryptFileId.split("#"); + if (ArrayUtil.isEmpty(split) || split.length != 3) { + throw BizException.wrap("文件ID无效"); + } + return PreviewFileIdBO.builder() + .fileId(split[0]) + .expireTime(Long.parseLong(split[1])) + .fileOrigin(FileOrigin.valueOf(split[2])) + .build(); } - public void downloadFile(Long fileId, HttpServletResponse response) { + public void downloadFile(String fileId, HttpServletResponse response) { try { - fileService.download(fileId, response); + PreviewFileIdBO previewFileId = parseFileId(fileId); + if (previewFileId.getExpireTime() != null + && previewFileId.getExpireTime() > 0 + && System.currentTimeMillis() > previewFileId.getExpireTime()) { + throw BizException.wrap("文件地址已过期,请重试"); + } + if (FileOrigin.MH.equals(previewFileId.getFileOrigin())) { + mhFileClient.download(previewFileId.getFileId(), response); + } else if (FileOrigin.OSS.equals(previewFileId.getFileOrigin())) { + fileService.download(Long.valueOf(previewFileId.getFileId()), response); + } else { + throw BizException.wrap("文件类型不支持"); + } } catch (Exception e) { log.info("文件下载失败:{}", fileId, e); throw BizException.wrap("文件下载失败:%s", fileId); diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/external/controller/FilePreviewController.java b/hz-pm-api/src/main/java/com/hz/pm/api/external/controller/FilePreviewController.java index c9fb6b5..32cf876 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/external/controller/FilePreviewController.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/external/controller/FilePreviewController.java @@ -36,7 +36,7 @@ public class FilePreviewController { @ApiOperation("文件下载(不鉴权)") @GetMapping("/anonymous/down/{fileId}") - public void anonymousFileDown(@PathVariable Long fileId, HttpServletResponse response) { + public void anonymousFileDown(@PathVariable String fileId, HttpServletResponse response) { filePreviewClient.downloadFile(fileId, response); } diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/external/controller/MhApiController.java b/hz-pm-api/src/main/java/com/hz/pm/api/external/controller/MhApiController.java index bcda037..6daeba2 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/external/controller/MhApiController.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/external/controller/MhApiController.java @@ -38,13 +38,20 @@ public class MhApiController { return mhApiClient.dictListByType(dictType); } - @GetMapping({"/anonymous/file/download/{fileId}", "/file/download/{fileId}"}) + @GetMapping("/file/download/{fileId}") @WebLog("下载信创平台文件") @ApiOperation("下载信创平台文件") public void download(@PathVariable String fileId, HttpServletResponse response) { mhFileClient.download(fileId, response); } + @GetMapping("/anonymous/file/download/{fileId}") + @WebLog("下载信创平台文件") + @ApiOperation("下载信创平台文件") + public void anonymousDownload(@PathVariable String fileId, HttpServletResponse response) { + mhFileClient.download(fileId, response); + } + @GetMapping("/file/listFileInfo") @ApiOperation("获取文件详情") public List listFileInfo(@RequestParam String fileIds) { diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/external/model/PreviewFileIdBO.java b/hz-pm-api/src/main/java/com/hz/pm/api/external/model/PreviewFileIdBO.java new file mode 100644 index 0000000..2fbce05 --- /dev/null +++ b/hz-pm-api/src/main/java/com/hz/pm/api/external/model/PreviewFileIdBO.java @@ -0,0 +1,31 @@ +package com.hz.pm.api.external.model; + +import com.hz.pm.api.common.enumeration.FileOrigin; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * PreviewFileIdBO + *

+ * + * @author WendyYang + * @since 14:12 2024/11/19 + */ +@Builder +@Getter +@Setter +public class PreviewFileIdBO { + + private String fileId; + + private Long expireTime; + + private FileOrigin fileOrigin; + + public String concat() { + return this.fileId + "#" + this.expireTime + "#" + this.fileOrigin; + } + +} diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/user/security/auth/mh/MhLoginUserDetailService.java b/hz-pm-api/src/main/java/com/hz/pm/api/user/security/auth/mh/MhLoginUserDetailService.java index 33c98ad..3447801 100644 --- a/hz-pm-api/src/main/java/com/hz/pm/api/user/security/auth/mh/MhLoginUserDetailService.java +++ b/hz-pm-api/src/main/java/com/hz/pm/api/user/security/auth/mh/MhLoginUserDetailService.java @@ -1,7 +1,6 @@ package com.hz.pm.api.user.security.auth.mh; -import cn.hutool.json.JSONUtil; import com.hz.pm.api.common.helper.UserInfoHelper; import com.hz.pm.api.user.convert.UserInfoConvertor; import com.hz.pm.api.user.security.auth.checker.UserLoginChecker; @@ -32,7 +31,7 @@ public class MhLoginUserDetailService implements UserDetailsService { public UserInfoDetails loadUserByUsername(String username) throws UsernameNotFoundException { UserFullInfoDTO userInfo = userInfoHelper.getUserFullInfoByMhUserIdOrOpenId(username); UserLoginChecker.checkLoginAuth(userInfo); - log.info("登录用户为:{}", JSONUtil.toJsonStr(userInfo)); + log.info("登录用户为:{} {}", userInfo.getUserId(), userInfo.getUsername()); return UserInfoConvertor.convert(userInfo); }