diff --git a/ruoyi-ui/src/utils/request.js b/ruoyi-ui/src/utils/request.js index 759f03433..c063ec300 100644 --- a/ruoyi-ui/src/utils/request.js +++ b/ruoyi-ui/src/utils/request.js @@ -73,6 +73,18 @@ service.interceptors.response.use(res => { type: 'error' }) return Promise.reject(new Error(msg)) + } else if (code === 901) { + Message({ + type: 'error', + duration: 0, + dangerouslyUseHTMLString: true, + message: '
演示模式,不发进行写操作
' + + '
 
' + + '
参考 https://www.iocoder.cn/Yudao/build-debugger-environment 教程
' + + '
 
' + + '
5 分钟搭建本地环境
', + }) + return Promise.reject(new Error(msg)) } else if (code !== 200) { Notification.error({ title: msg diff --git a/src/main/java/cn/iocoder/dashboard/common/exception/enums/GlobalErrorCodeConstants.java b/src/main/java/cn/iocoder/dashboard/common/exception/enums/GlobalErrorCodeConstants.java index 146de8078..adda623e3 100644 --- a/src/main/java/cn/iocoder/dashboard/common/exception/enums/GlobalErrorCodeConstants.java +++ b/src/main/java/cn/iocoder/dashboard/common/exception/enums/GlobalErrorCodeConstants.java @@ -32,6 +32,7 @@ public interface GlobalErrorCodeConstants { // ========== 自定义错误段 ========== ErrorCode REPEATED_REQUESTS = new ErrorCode(900, "重复请求,请稍后重试"); // 重复请求 + ErrorCode DEMO_DENY = new ErrorCode(901, "演示模式,禁止写操作"); ErrorCode UNKNOWN = new ErrorCode(999, "未知错误"); diff --git a/src/main/java/cn/iocoder/dashboard/framework/web/config/WebConfiguration.java b/src/main/java/cn/iocoder/dashboard/framework/web/config/WebConfiguration.java index b87c49008..2f4e7a378 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/web/config/WebConfiguration.java +++ b/src/main/java/cn/iocoder/dashboard/framework/web/config/WebConfiguration.java @@ -2,7 +2,9 @@ package cn.iocoder.dashboard.framework.web.config; import cn.iocoder.dashboard.framework.web.core.enums.FilterOrderEnum; import cn.iocoder.dashboard.framework.web.core.filter.CacheRequestBodyFilter; +import cn.iocoder.dashboard.framework.web.core.filter.DemoFilter; import cn.iocoder.dashboard.framework.web.core.filter.XssFilter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; @@ -68,6 +70,15 @@ public class WebConfiguration implements WebMvcConfigurer { return createFilterBean(new XssFilter(properties, pathMatcher), FilterOrderEnum.XSS_FILTER); } + /** + * 创建 DemoFilter Bean,演示模式 + */ + @Bean + @ConditionalOnProperty(value = "yudao.demo", havingValue = "true") + public FilterRegistrationBean demoFilter() { + return createFilterBean(new DemoFilter(), FilterOrderEnum.DEMO_FILTER); + } + private static FilterRegistrationBean createFilterBean(T filter, Integer order) { FilterRegistrationBean bean = new FilterRegistrationBean<>(filter); bean.setOrder(order); diff --git a/src/main/java/cn/iocoder/dashboard/framework/web/core/enums/FilterOrderEnum.java b/src/main/java/cn/iocoder/dashboard/framework/web/core/enums/FilterOrderEnum.java index 31b25087e..7c6ac8c6a 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/web/core/enums/FilterOrderEnum.java +++ b/src/main/java/cn/iocoder/dashboard/framework/web/core/enums/FilterOrderEnum.java @@ -9,6 +9,7 @@ public interface FilterOrderEnum { int CORS_FILTER = Integer.MIN_VALUE; + int REQUEST_BODY_CACHE_FILTER = Integer.MIN_VALUE + 500; // OrderedRequestContextFilter 默认为 -105,用于国际化上下文等等 @@ -19,4 +20,6 @@ public interface FilterOrderEnum { // Spring Security Filter 默认为 -100,可见 SecurityProperties 配置属性类 + int DEMO_FILTER = Integer.MAX_VALUE; + } diff --git a/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/DemoFilter.java b/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/DemoFilter.java new file mode 100644 index 000000000..f5f008947 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/DemoFilter.java @@ -0,0 +1,35 @@ +package cn.iocoder.dashboard.framework.web.core.filter; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.dashboard.common.pojo.CommonResult; +import cn.iocoder.dashboard.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.dashboard.util.servlet.ServletUtils; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import static cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants.DEMO_DENY; + +/** + * 演示 Filter,禁止用户发起写操作,避免影响测试数据 + * + * @author 芋道源码 + */ +public class DemoFilter extends OncePerRequestFilter { + + @Override + protected boolean shouldNotFilter(HttpServletRequest request) { + String method = request.getMethod(); + return !StrUtil.equalsAnyIgnoreCase(method, "POST", "PUT", "DELETE") // 写操作时,不进行过滤率 + || SecurityFrameworkUtils.getLoginUser() == null; // 非登陆用户时,不进行过滤 + } + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) { + // 直接返回 DEMO_DENY 的结果。即,请求不继续 + ServletUtils.writeJSON(response, CommonResult.error(DEMO_DENY)); + } + +} diff --git a/src/main/resources/application-dev.yaml b/src/main/resources/application-dev.yaml index b0a96fb04..39ae7e851 100644 --- a/src/main/resources/application-dev.yaml +++ b/src/main/resources/application-dev.yaml @@ -161,3 +161,4 @@ yudao: exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求 - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 + demo: true # 开启演示模式 diff --git a/src/main/resources/application-local.yaml b/src/main/resources/application-local.yaml index fdb260758..5736736c5 100644 --- a/src/main/resources/application-local.yaml +++ b/src/main/resources/application-local.yaml @@ -161,3 +161,4 @@ yudao: exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求 - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 + demo: false # 关闭演示模式