From 1d2c8378f7b84521cb513967bd25517da9376fb2 Mon Sep 17 00:00:00 2001
From: RuoYi <yzz_ivy@163.com>
Date: Tue, 02 Sep 2025 13:26:33 +0800
Subject: [PATCH] 文件支持防盗链配置

---
 ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/filter/RefererFilter.java |   77 +++++++++++++++++++++++++
 ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/FilterConfig.java  |   46 +++++++++++++++
 sql/ry_config_20250902.sql                                                      |    2 
 3 files changed, 124 insertions(+), 1 deletions(-)

diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/FilterConfig.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/FilterConfig.java
new file mode 100644
index 0000000..09136bb
--- /dev/null
+++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/FilterConfig.java
@@ -0,0 +1,46 @@
+package com.ruoyi.file.config;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.servlet.DispatcherType;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import com.ruoyi.file.filter.RefererFilter;
+
+/**
+ * Filter配置
+ *
+ * @author ruoyi
+ */
+@Configuration
+public class FilterConfig
+{
+    /**
+     * 资源映射路径 前缀
+     */
+    @Value("${file.prefix}")
+    public String localFilePrefix;
+    
+    @Value("${referer.allowed-domains}")
+    private String allowedDomains;
+    
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    @Bean
+    @ConditionalOnProperty(value = "referer.enabled", havingValue = "true")
+    public FilterRegistrationBean refererFilterRegistration()
+    {
+        FilterRegistrationBean registration = new FilterRegistrationBean();
+        registration.setDispatcherTypes(DispatcherType.REQUEST);
+        registration.setFilter(new RefererFilter());
+        registration.addUrlPatterns(localFilePrefix + "/*");
+        registration.setName("refererFilter");
+        registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
+        Map<String, String> initParameters = new HashMap<String, String>();
+        initParameters.put("allowedDomains", allowedDomains);
+        registration.setInitParameters(initParameters);
+        return registration;
+    }
+}
diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/filter/RefererFilter.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/filter/RefererFilter.java
new file mode 100644
index 0000000..0aafbe7
--- /dev/null
+++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/filter/RefererFilter.java
@@ -0,0 +1,77 @@
+package com.ruoyi.file.filter;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * 防盗链过滤器
+ * 
+ * @author ruoyi
+ */
+public class RefererFilter implements Filter
+{
+    /**
+     * 允许的域名列表
+     */
+    public List<String> allowedDomains;
+
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException
+    {
+        String domains = filterConfig.getInitParameter("allowedDomains");
+        this.allowedDomains = Arrays.asList(domains.split(","));
+    }
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+            throws IOException, ServletException
+    {
+        HttpServletRequest req = (HttpServletRequest) request;
+        HttpServletResponse resp = (HttpServletResponse) response;
+
+        String referer = req.getHeader("Referer");
+
+        // 如果Referer为空,拒绝访问
+        if (referer == null || referer.isEmpty())
+        {
+            resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied: Referer header is required");
+            return;
+        }
+
+        // 检查Referer是否在允许的域名列表中
+        boolean allowed = false;
+        for (String domain : allowedDomains)
+        {
+            if (referer.contains(domain))
+            {
+                allowed = true;
+                break;
+            }
+        }
+
+        // 根据检查结果决定是否放行
+        if (allowed)
+        {
+            chain.doFilter(request, response);
+        }
+        else
+        {
+            resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied: Referer '" + referer + "' is not allowed");
+        }
+    }
+
+    @Override
+    public void destroy()
+    {
+
+    }
+}
\ No newline at end of file
diff --git a/sql/ry_config_20250224.sql b/sql/ry_config_20250902.sql
similarity index 96%
rename from sql/ry_config_20250224.sql
rename to sql/ry_config_20250902.sql
index a01ed9f..8ea4884 100644
--- a/sql/ry_config_20250224.sql
+++ b/sql/ry_config_20250902.sql
@@ -40,7 +40,7 @@
 (5,'ruoyi-system-dev.yml','DEFAULT_GROUP','# spring配置\nspring:\n  redis:\n    host: localhost\n    port: 6379\n    password: \n  datasource:\n    druid:\n      stat-view-servlet:\n        enabled: true\n        loginUsername: ruoyi\n        loginPassword: 123456\n    dynamic:\n      druid:\n        initial-size: 5\n        min-idle: 5\n        maxActive: 20\n        maxWait: 60000\n        connectTimeout: 30000\n        socketTimeout: 60000\n        timeBetweenEvictionRunsMillis: 60000\n        minEvictableIdleTimeMillis: 300000\n        validationQuery: SELECT 1 FROM DUAL\n        testWhileIdle: true\n        testOnBorrow: false\n        testOnReturn: false\n        poolPreparedStatements: true\n        maxPoolPreparedStatementPerConnectionSize: 20\n        filters: stat,slf4j\n        connectionProperties: druid.stat.mergeSql\\=true;druid.stat.slowSqlMillis\\=5000\n      datasource:\n          # 主库数据源\n          master:\n            driver-class-name: com.mysql.cj.jdbc.Driver\n            url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n            username: root\n            password: password\n          # 从库数据源\n          # slave:\n            # username: \n            # password: \n            # url: \n            # driver-class-name: \n\n# mybatis配置\nmybatis:\n    # 搜索指定包别名\n    typeAliasesPackage: com.ruoyi.system\n    # 配置mapper的扫描,找到所有的mapper.xml映射文件\n    mapperLocations: classpath:mapper/**/*.xml\n\n# springdoc配置\nspringdoc:\n  gatewayUrl: http://localhost:8080/${spring.application.name}\n  api-docs:\n    # 是否开启接口文档\n    enabled: true\n  info:\n    # 标题\n    title: \'系统模块接口文档\'\n    # 描述\n    description: \'系统模块接口描述\'\n    # 作者信息\n    contact:\n      name: RuoYi\n      url: https://ruoyi.vip\n','786c7daf4543411fc65c3e48dfb15243','2020-11-20 00:00:00','2024-09-02 12:14:33','nacos','0:0:0:0:0:0:0:1','','','系统模块','null','null','yaml','',''),
 (6,'ruoyi-gen-dev.yml','DEFAULT_GROUP','# spring配置\nspring:\n  redis:\n    host: localhost\n    port: 6379\n    password: \n  datasource:\n    driver-class-name: com.mysql.cj.jdbc.Driver\n    url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n    username: root\n    password: password\n\n# mybatis配置\nmybatis:\n    # 搜索指定包别名\n    typeAliasesPackage: com.ruoyi.gen.domain\n    # 配置mapper的扫描,找到所有的mapper.xml映射文件\n    mapperLocations: classpath:mapper/**/*.xml\n\n# springdoc配置\nspringdoc:\n  gatewayUrl: http://localhost:8080/${spring.application.name}\n  api-docs:\n    # 是否开启接口文档\n    enabled: true\n  info:\n    # 标题\n    title: \'代码生成接口文档\'\n    # 描述\n    description: \'代码生成接口描述\'\n    # 作者信息\n    contact:\n      name: RuoYi\n      url: https://ruoyi.vip\n\n# 代码生成\ngen:\n  # 作者\n  author: ruoyi\n  # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool\n  packageName: com.ruoyi.system\n  # 自动去除表前缀,默认是false\n  autoRemovePre: false\n  # 表前缀(生成类名不会包含表前缀,多个用逗号分隔)\n  tablePrefix: sys_\n  # 是否允许生成文件覆盖到本地(自定义路径),默认不允许\n  allowOverwrite: false','43d807aa0a4accbb193b6dc7e38ac8a3','2020-11-20 00:00:00','2024-12-25 08:29:33','nacos','0:0:0:0:0:0:0:1','','','代码生成','null','null','yaml','',''),
 (7,'ruoyi-job-dev.yml','DEFAULT_GROUP','# spring配置\nspring:\n  redis:\n    host: localhost\n    port: 6379\n    password: \n  datasource:\n    driver-class-name: com.mysql.cj.jdbc.Driver\n    url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\n    username: root\n    password: password\n\n# mybatis配置\nmybatis:\n    # 搜索指定包别名\n    typeAliasesPackage: com.ruoyi.job.domain\n    # 配置mapper的扫描,找到所有的mapper.xml映射文件\n    mapperLocations: classpath:mapper/**/*.xml\n\n# springdoc配置\nspringdoc:\n  gatewayUrl: http://localhost:8080/${spring.application.name}\n  api-docs:\n    # 是否开启接口文档\n    enabled: true\n  info:\n    # 标题\n    title: \'定时任务接口文档\'\n    # 描述\n    description: \'定时任务接口描述\'\n    # 作者信息\n    contact:\n      name: RuoYi\n      url: https://ruoyi.vip\n','f78483f845777335b9ed4a9f84758848','2020-11-20 00:00:00','2024-09-02 12:14:56','nacos','0:0:0:0:0:0:0:1','','','定时任务','null','null','yaml','',''),
-(8,'ruoyi-file-dev.yml','DEFAULT_GROUP','# 本地文件上传    \r\nfile:\r\n    domain: http://127.0.0.1:9300\r\n    path: D:/ruoyi/uploadPath\r\n    prefix: /statics\r\n\r\n# FastDFS配置\r\nfdfs:\r\n  domain: http://8.129.231.12\r\n  soTimeout: 3000\r\n  connectTimeout: 2000\r\n  trackerList: 8.129.231.12:22122\r\n\r\n# Minio配置\r\nminio:\r\n  url: http://8.129.231.12:9000\r\n  accessKey: minioadmin\r\n  secretKey: minioadmin\r\n  bucketName: test','5382b93f3d8059d6068c0501fdd41195','2020-11-20 00:00:00','2020-12-21 21:01:59',NULL,'0:0:0:0:0:0:0:1','','','文件服务','null','null','yaml',NULL,''),
+(8,'ruoyi-file-dev.yml','DEFAULT_GROUP','# 本地文件上传    \nfile:\n    domain: http://127.0.0.1:9300\n    path: D:/ruoyi/uploadPath\n    prefix: /statics\n\n# FastDFS配置\nfdfs:\n  domain: http://127.0.0.1\n  soTimeout: 3000\n  connectTimeout: 2000\n  trackerList: 127.0.0.1:22122\n\n# Minio配置\nminio:\n  url: http://127.0.0.1:9000\n  accessKey: minioadmin\n  secretKey: minioadmin\n  bucketName: test\n\n  # 防盗链配置\nreferer:\n  # 防盗链开关\n  enabled: false\n  # 允许的域名列表\n  allowed-domains: localhost,127.0.0.1,ruoyi.vip,www.ruoyi.vip\n','095791a04211d6e3d294359b21357394','2020-11-20 00:00:00','2025-09-02 05:10:11','nacos','0:0:0:0:0:0:0:1','','','文件服务','null','null','yaml','',''),
 (9,'sentinel-ruoyi-gateway','DEFAULT_GROUP','[\r\n    {\r\n        \"resource\": \"ruoyi-auth\",\r\n        \"count\": 500,\r\n        \"grade\": 1,\r\n        \"limitApp\": \"default\",\r\n        \"strategy\": 0,\r\n        \"controlBehavior\": 0\r\n    },\r\n	{\r\n        \"resource\": \"ruoyi-system\",\r\n        \"count\": 1000,\r\n        \"grade\": 1,\r\n        \"limitApp\": \"default\",\r\n        \"strategy\": 0,\r\n        \"controlBehavior\": 0\r\n    },\r\n	{\r\n        \"resource\": \"ruoyi-gen\",\r\n        \"count\": 200,\r\n        \"grade\": 1,\r\n        \"limitApp\": \"default\",\r\n        \"strategy\": 0,\r\n        \"controlBehavior\": 0\r\n    },\r\n	{\r\n        \"resource\": \"ruoyi-job\",\r\n        \"count\": 300,\r\n        \"grade\": 1,\r\n        \"limitApp\": \"default\",\r\n        \"strategy\": 0,\r\n        \"controlBehavior\": 0\r\n    }\r\n]','9f3a3069261598f74220bc47958ec252','2020-11-20 00:00:00','2020-11-20 00:00:00',NULL,'0:0:0:0:0:0:0:1','','','限流策略','null','null','json',NULL,'');
 
 

--
Gitblit v1.9.3