限制单 IP 直链单位时间内下载次数

This commit is contained in:
zhaojun
2023-03-05 15:23:47 +08:00
parent 96b71e4f8d
commit 300e58e92c
5 changed files with 53 additions and 28 deletions

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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<String, Integer> 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);
}