diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index d0af381a..8abf1a68 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -17,8 +17,8 @@ spring: type: ${spring.datasource.type} driverClassName: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/ruoyi-ai?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true - username: ruoyi-ai - password: ruoyi-ai + username: root + password: root hikari: # 最大连接池数量 diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 39b604ff..fac52415 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -2,15 +2,13 @@ # 项目相关配置 ruoyi: # 名称 - name: "ruoyi" + name: "ruoyi-ai" # 版本 version: ${revision} # 版权年份 copyrightYear: 2025 # 实例演示开关 - demoEnabled: true - # 获取ip地址开关 - addressEnabled: false + demoEnabled: false captcha: enable: false diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/org/ruoyi/common/web/config/ResourcesConfig.java b/ruoyi-common/ruoyi-common-web/src/main/java/org/ruoyi/common/web/config/ResourcesConfig.java index 3acd4302..37072b54 100644 --- a/ruoyi-common/ruoyi-common-web/src/main/java/org/ruoyi/common/web/config/ResourcesConfig.java +++ b/ruoyi-common/ruoyi-common-web/src/main/java/org/ruoyi/common/web/config/ResourcesConfig.java @@ -1,6 +1,9 @@ package org.ruoyi.common.web.config; + +import org.ruoyi.common.web.interceptor.DemoModeInterceptor; import org.ruoyi.common.web.interceptor.PlusWebInvokeTimeInterceptor; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.web.cors.CorsConfiguration; @@ -18,10 +21,35 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @AutoConfiguration public class ResourcesConfig implements WebMvcConfigurer { + @Autowired(required = false) + private DemoModeInterceptor demoModeInterceptor; + @Override public void addInterceptors(InterceptorRegistry registry) { // 全局访问性能拦截 registry.addInterceptor(new PlusWebInvokeTimeInterceptor()); + + // 演示模式拦截器 + if (demoModeInterceptor != null) { + registry.addInterceptor(demoModeInterceptor) + .addPathPatterns("/**") // 拦截所有路径 + .excludePathPatterns( + // 排除静态资源 + "/css/**", + "/js/**", + "/images/**", + "/fonts/**", + "/favicon.ico", + // 排除错误页面 + "/error", + // 排除API文档 + "/*/api-docs/**", + "/swagger-ui/**", + "/webjars/**", + // 排除监控端点 + "/actuator/**" + ); + } } @Override diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/org/ruoyi/common/web/interceptor/DemoModeInterceptor.java b/ruoyi-common/ruoyi-common-web/src/main/java/org/ruoyi/common/web/interceptor/DemoModeInterceptor.java new file mode 100644 index 00000000..563f8169 --- /dev/null +++ b/ruoyi-common/ruoyi-common-web/src/main/java/org/ruoyi/common/web/interceptor/DemoModeInterceptor.java @@ -0,0 +1,100 @@ +package org.ruoyi.common.web.interceptor; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.ruoyi.common.core.config.RuoYiConfig; +import org.ruoyi.common.core.exception.DemoModeException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +/** + * 演示模式拦截器 + * 全局拦截所有编辑操作(POST、PUT、DELETE、PATCH) + * + * @author ruoyi + */ +@Slf4j +@Component +public class DemoModeInterceptor implements HandlerInterceptor { + + @Autowired + private RuoYiConfig ruoYiConfig; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + // 如果演示模式未开启,直接放行 + if (!ruoYiConfig.isDemoEnabled()) { + return true; + } + + String method = request.getMethod(); + String requestURI = request.getRequestURI(); + + // 拦截所有编辑操作 + if (isEditOperation(method)) { + // 排除一些特殊的只读操作 + if (isExcludedPath(requestURI)) { + return true; + } + + log.warn("演示模式拦截: {} {}", method, requestURI); + throw new DemoModeException(); + } + + return true; + } + + /** + * 判断是否为编辑操作 + */ + private boolean isEditOperation(String method) { + return "POST".equalsIgnoreCase(method) + || "PUT".equalsIgnoreCase(method) + || "DELETE".equalsIgnoreCase(method) + || "PATCH".equalsIgnoreCase(method); + } + + /** + * 判断是否为排除的路径(这些路径即使是POST等方法也不拦截) + */ + private boolean isExcludedPath(String requestURI) { + // 排除登录相关 + if (requestURI.contains("/auth/login") || requestURI.contains("/auth/logout")) { + return true; + } + + // 排除导出操作(虽然是POST但是只读操作) + if (requestURI.contains("/export")) { + return true; + } + + // 排除查询操作(一些复杂查询使用POST) + if (requestURI.contains("/list") || requestURI.contains("/query")) { + return true; + } + + // 排除聊天接口(核心功能) + if (requestURI.contains("/chat/send") || requestURI.contains("/chat/upload")) { + return true; + } + + // 排除文件上传预览等只读操作 + if (requestURI.contains("/upload") || requestURI.contains("/preview")) { + return true; + } + + // 排除支付回调 + if (requestURI.contains("/pay/returnUrl") || requestURI.contains("/pay/notifyUrl")) { + return true; + } + + // 排除重置密码(用户自己的操作) + if (requestURI.contains("/auth/reset/password")) { + return true; + } + + return false; + } +}