From 300e58e92c67b30f18e403eb31609c90af516a43 Mon Sep 17 00:00:00 2001 From: zhaojun <873019219@qq.com> Date: Sun, 5 Mar 2023 15:23:47 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20=E9=99=90=E5=88=B6=E5=8D=95=20IP?= =?UTF-8?q?=20=E7=9B=B4=E9=93=BE=E5=8D=95=E4=BD=8D=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E5=86=85=E4=B8=8B=E8=BD=BD=E6=AC=A1=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/model/dto/SystemConfigDTO.java | 6 ++ .../request/UpdateLinkSettingRequest.java | 7 +- .../storage/filter/DownloadLinkFilter.java | 64 +++++++++++-------- ...stem_config_add_field_link_limit_field.sql | 2 + ...stem_config_add_field_link_limit_field.sql | 2 + 5 files changed, 53 insertions(+), 28 deletions(-) create mode 100644 src/main/resources/db/migration-mysql/V17__system_config_add_field_link_limit_field.sql create mode 100644 src/main/resources/db/migration-sqlite/V17__system_config_add_field_link_limit_field.sql diff --git a/src/main/java/im/zhaojun/zfile/module/config/model/dto/SystemConfigDTO.java b/src/main/java/im/zhaojun/zfile/module/config/model/dto/SystemConfigDTO.java index f5bc6cc..00602b5 100644 --- a/src/main/java/im/zhaojun/zfile/module/config/model/dto/SystemConfigDTO.java +++ b/src/main/java/im/zhaojun/zfile/module/config/model/dto/SystemConfigDTO.java @@ -153,4 +153,10 @@ public class SystemConfigDTO { @ApiModelProperty(value = "站点 Logo 链接打开方式", example = "_blank") private String siteHomeLogoTargetMode; + @ApiModelProperty(value = "限制直链下载秒数", example = "_blank") + private Integer linkLimitSecond; + + @ApiModelProperty(value = "限制直链下载次数", example = "_blank") + private Integer linkDownloadLimit; + } \ No newline at end of file diff --git a/src/main/java/im/zhaojun/zfile/module/config/model/request/UpdateLinkSettingRequest.java b/src/main/java/im/zhaojun/zfile/module/config/model/request/UpdateLinkSettingRequest.java index dff42ab..808d9b9 100644 --- a/src/main/java/im/zhaojun/zfile/module/config/model/request/UpdateLinkSettingRequest.java +++ b/src/main/java/im/zhaojun/zfile/module/config/model/request/UpdateLinkSettingRequest.java @@ -37,8 +37,13 @@ public class UpdateLinkSettingRequest { @ApiModelProperty(value = "是否显示生成路径链接功能", example = "true", required = true) private Boolean showPathLink; - + @ApiModelProperty(value = "是否允许路径直链可直接访问", example = "true", required = true) private Boolean allowPathLinkAnonAccess; + @ApiModelProperty(value = "限制直链下载秒数", example = "_blank") + private Integer linkLimitSecond; + + @ApiModelProperty(value = "限制直链下载次数", example = "_blank") + private Integer linkDownloadLimit; } \ No newline at end of file diff --git a/src/main/java/im/zhaojun/zfile/module/storage/filter/DownloadLinkFilter.java b/src/main/java/im/zhaojun/zfile/module/storage/filter/DownloadLinkFilter.java index 34c99ea..ca42f38 100644 --- a/src/main/java/im/zhaojun/zfile/module/storage/filter/DownloadLinkFilter.java +++ b/src/main/java/im/zhaojun/zfile/module/storage/filter/DownloadLinkFilter.java @@ -1,28 +1,24 @@ package im.zhaojun.zfile.module.storage.filter; +import cn.hutool.cache.impl.TimedCache; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.BooleanUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.servlet.ServletUtil; import cn.hutool.extra.spring.SpringUtil; -import im.zhaojun.zfile.module.link.model.entity.ShortLink; -import im.zhaojun.zfile.module.storage.model.entity.StorageSource; -import im.zhaojun.zfile.module.log.service.DownloadLogService; -import im.zhaojun.zfile.module.filter.service.FilterConfigService; -import im.zhaojun.zfile.module.link.service.ShortLinkService; -import im.zhaojun.zfile.module.storage.service.StorageSourceService; -import im.zhaojun.zfile.module.config.service.SystemConfigService; import im.zhaojun.zfile.core.constant.ZFileConstant; -import im.zhaojun.zfile.module.storage.context.StorageSourceContext; import im.zhaojun.zfile.core.util.StringUtils; import im.zhaojun.zfile.module.config.model.dto.SystemConfigDTO; +import im.zhaojun.zfile.module.config.service.SystemConfigService; +import im.zhaojun.zfile.module.filter.service.FilterConfigService; +import im.zhaojun.zfile.module.link.model.entity.ShortLink; +import im.zhaojun.zfile.module.link.service.ShortLinkService; +import im.zhaojun.zfile.module.storage.model.entity.StorageSource; +import im.zhaojun.zfile.module.storage.service.StorageSourceService; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpHeaders; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; +import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -43,14 +39,15 @@ public class DownloadLinkFilter implements Filter { private StorageSourceService storageSourceService; - private StorageSourceContext storageSourceContext; - - private DownloadLogService downloadLogService; private ShortLinkService shortLinkService; private FilterConfigService filterConfigService; + private TimedCache timedCache; + + private static final String shortLinkPrefix = "/s/"; + @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (systemConfigService == null) { @@ -61,13 +58,6 @@ public class DownloadLinkFilter implements Filter { storageSourceService = SpringUtil.getBean(StorageSourceService.class); } - if (storageSourceContext == null) { - storageSourceContext = SpringUtil.getBean(StorageSourceContext.class); - } - - if (downloadLogService == null) { - downloadLogService = SpringUtil.getBean(DownloadLogService.class); - } if (shortLinkService == null) { shortLinkService = SpringUtil.getBean(ShortLinkService.class); @@ -97,8 +87,28 @@ public class DownloadLinkFilter implements Filter { // 获取系统配置的直链前缀 SystemConfigDTO systemConfig = systemConfigService.getSystemConfig(); String directLinkPrefix = systemConfig.getDirectLinkPrefix(); - if (StrUtil.equalsIgnoreCase(currentRequestPrefix, directLinkPrefix)) { - + boolean isDirectLink = StrUtil.equalsIgnoreCase(currentRequestPrefix, directLinkPrefix); + boolean isShortLink = StrUtil.startWith(currentRequestPrefix, shortLinkPrefix); + if (isDirectLink || isShortLink) { + synchronized (this) { + Integer linkLimitSecond = systemConfig.getLinkLimitSecond(); + Integer linkDownloadLimit = systemConfig.getLinkDownloadLimit(); + if (timedCache == null) { + timedCache = new TimedCache<>(linkLimitSecond * 1000); + } + String clientIp = ServletUtil.getClientIP(httpServletRequest); + Integer ipDownloadCount = timedCache.get(clientIp, false, () -> 1); + if (ipDownloadCount != null && ipDownloadCount > linkDownloadLimit) { + httpServletResponse.setHeader(HttpHeaders.CONTENT_TYPE, "text/plain;charset=utf-8"); + httpServletResponse.getWriter().write("当前系统限制每 " + systemConfig.getLinkLimitSecond() + " 秒内只能访问 " + linkDownloadLimit + " 次直链."); + return; + } + timedCache.put(clientIp, ipDownloadCount + 1); + } + + } + + if (isDirectLink) { if (BooleanUtil.isFalse(systemConfig.getShowPathLink())) { httpServletResponse.setHeader(HttpHeaders.CONTENT_TYPE, "text/plain;charset=utf-8"); httpServletResponse.getWriter().write("当前系统不允许使用直链."); @@ -153,7 +163,7 @@ public class DownloadLinkFilter implements Filter { ShortLink shortLink = shortLinkService.findByStorageIdAndUrl(storageId, filePath); SystemConfigDTO systemConfig = systemConfigService.getSystemConfig(); - + // 如果没有短链,则生成短链 if (shortLink == null) { if (BooleanUtil.isFalse(systemConfig.getAllowPathLinkAnonAccess())) { @@ -162,7 +172,7 @@ public class DownloadLinkFilter implements Filter { response.getWriter().write("该文件未生成直链, 无法下载,请联系管理员!"); return; } - + shortLink = shortLinkService.generatorShortLink(storageId, filePath); } diff --git a/src/main/resources/db/migration-mysql/V17__system_config_add_field_link_limit_field.sql b/src/main/resources/db/migration-mysql/V17__system_config_add_field_link_limit_field.sql new file mode 100644 index 0000000..7df67f4 --- /dev/null +++ b/src/main/resources/db/migration-mysql/V17__system_config_add_field_link_limit_field.sql @@ -0,0 +1,2 @@ +INSERT INTO system_config (`name`, `title`, `value`) VALUES ('linkLimitSecond', '限制直链下载秒数', '3600'); +INSERT INTO system_config (`name`, `title`, `value`) VALUES ('linkDownloadLimit', '限制直链下载次数', '10000'); \ No newline at end of file diff --git a/src/main/resources/db/migration-sqlite/V17__system_config_add_field_link_limit_field.sql b/src/main/resources/db/migration-sqlite/V17__system_config_add_field_link_limit_field.sql new file mode 100644 index 0000000..7df67f4 --- /dev/null +++ b/src/main/resources/db/migration-sqlite/V17__system_config_add_field_link_limit_field.sql @@ -0,0 +1,2 @@ +INSERT INTO system_config (`name`, `title`, `value`) VALUES ('linkLimitSecond', '限制直链下载秒数', '3600'); +INSERT INTO system_config (`name`, `title`, `value`) VALUES ('linkDownloadLimit', '限制直链下载次数', '10000'); \ No newline at end of file