diff --git a/backend/src/main/java/io/metersphere/commons/utils/ShiroUtils.java b/backend/src/main/java/io/metersphere/commons/utils/ShiroUtils.java index e48a56c994..18c222d1ba 100644 --- a/backend/src/main/java/io/metersphere/commons/utils/ShiroUtils.java +++ b/backend/src/main/java/io/metersphere/commons/utils/ShiroUtils.java @@ -44,6 +44,10 @@ public class ShiroUtils { // filterChainDefinitionMap.put("/document/**", "anon"); } + public static void ignoreCsrfFilter(Map filterChainDefinitionMap) { + filterChainDefinitionMap.put("/", "apikey, authc"); // 跳转到 / 不用校验 csrf + } + public static Cookie getSessionIdCookie(){ SimpleCookie sessionIdCookie = new SimpleCookie(); sessionIdCookie.setPath("/"); diff --git a/backend/src/main/java/io/metersphere/config/ShiroConfig.java b/backend/src/main/java/io/metersphere/config/ShiroConfig.java index 05729f12d8..4755bbe8d4 100644 --- a/backend/src/main/java/io/metersphere/config/ShiroConfig.java +++ b/backend/src/main/java/io/metersphere/config/ShiroConfig.java @@ -47,9 +47,11 @@ public class ShiroConfig implements EnvironmentAware { shiroFilterFactoryBean.getFilters().put("apikey", new ApiKeyFilter()); shiroFilterFactoryBean.getFilters().put("csrf", new CsrfFilter()); Map filterChainDefinitionMap = shiroFilterFactoryBean.getFilterChainDefinitionMap(); + ShiroUtils.loadBaseFilterChain(filterChainDefinitionMap); - filterChainDefinitionMap.put("/", "apikey, authc"); // 跳转到 / 不用校验 csrf + ShiroUtils.ignoreCsrfFilter(filterChainDefinitionMap); + filterChainDefinitionMap.put("/**", "apikey, csrf, authc"); return shiroFilterFactoryBean; } diff --git a/backend/src/main/java/io/metersphere/security/CsrfFilter.java b/backend/src/main/java/io/metersphere/security/CsrfFilter.java index a426c14d35..ea21966c4b 100644 --- a/backend/src/main/java/io/metersphere/security/CsrfFilter.java +++ b/backend/src/main/java/io/metersphere/security/CsrfFilter.java @@ -32,6 +32,12 @@ public class CsrfFilter extends AnonymousFilter { if (ApiKeyHandler.isApiKeyCall(WebUtils.toHttp(request))) { return true; } + // websocket 不需要csrf + String websocketKey = httpServletRequest.getHeader("Sec-WebSocket-Key"); + if (StringUtils.isNotBlank(websocketKey)) { + return true; + } + // 请求头取出的token value String csrfToken = httpServletRequest.getHeader(TOKEN_NAME); // 校验 token diff --git a/frontend/src/business/components/performance/test/components/PerformanceAdvancedConfig.vue b/frontend/src/business/components/performance/test/components/PerformanceAdvancedConfig.vue index 6c6348bc68..5a835228bd 100644 --- a/frontend/src/business/components/performance/test/components/PerformanceAdvancedConfig.vue +++ b/frontend/src/business/components/performance/test/components/PerformanceAdvancedConfig.vue @@ -117,6 +117,36 @@ + + + + +
+ {{ $t('load_test.granularity') }} + + + + + + + + + +
+
+ + + + + +
+
+
@@ -134,6 +164,18 @@ export default { domains: [], params: [], statusCodeStr: '', + granularity: undefined, + granularityData: [ + {start: 0, end: 100, granularity: 1}, + {start: 101, end: 500, granularity: 5}, + {start: 501, end: 1000, granularity: 10}, + {start: 1001, end: 3000, granularity: 30}, + {start: 3001, end: 6000, granularity: 60}, + {start: 6001, end: 30000, granularity: 300}, + {start: 30001, end: 60000, granularity: 600}, + {start: 60001, end: 180000, granularity: 1800}, + {start: 180001, end: 360000, granularity: 3600}, + ] } }, props: { @@ -166,6 +208,7 @@ export default { this.statusCodeStr = this.statusCode.join(','); this.domains = data.domains || []; this.params = data.params || []; + this.granularity = data.granularity; } }); }, @@ -252,6 +295,7 @@ export default { statusCode: statusCode, params: this.params, domains: this.domains, + granularity: this.granularity, }; }, } @@ -287,4 +331,8 @@ export default { align: center; } +.pointer { + cursor: pointer; +} + diff --git a/frontend/src/i18n/en-US.js b/frontend/src/i18n/en-US.js index 355a4c20f0..ae093f2164 100644 --- a/frontend/src/i18n/en-US.js +++ b/frontend/src/i18n/en-US.js @@ -478,7 +478,8 @@ export default { delete_file: "The file already exists, please delete the file with the same name first!", thread_num: 'Concurrent users:', input_thread_num: 'Please enter the number of threads', - duration: 'Duration time (seconds):', + duration: 'Duration time (seconds)', + granularity: 'Aggregation time (seconds)', input_duration: 'Please enter a duration', rps_limit: 'RPS Limit:', input_rps_limit: 'Please enter a limit', diff --git a/frontend/src/i18n/zh-CN.js b/frontend/src/i18n/zh-CN.js index d9b59557f8..0e92251361 100644 --- a/frontend/src/i18n/zh-CN.js +++ b/frontend/src/i18n/zh-CN.js @@ -475,7 +475,8 @@ export default { delete_file: "文件已存在,请先删除同名文件!", thread_num: '并发用户数:', input_thread_num: '请输入线程数', - duration: '压测时长(秒):', + duration: '压测时长(秒)', + granularity: '聚合时间(秒)', input_duration: '请输入时长', rps_limit: 'RPS上限:', input_rps_limit: '请输入限制', diff --git a/frontend/src/i18n/zh-TW.js b/frontend/src/i18n/zh-TW.js index 2204bc6e0f..b42842b12c 100644 --- a/frontend/src/i18n/zh-TW.js +++ b/frontend/src/i18n/zh-TW.js @@ -475,7 +475,8 @@ export default { delete_file: "文件已存在,請先刪除同名文件!", thread_num: '並發用戶數:', input_thread_num: '請輸入線程數', - duration: '壓測時長(秒):', + duration: '壓測時長(秒)', + granularity: '聚合時間(秒)', input_duration: '請輸入時長', rps_limit: 'RPS上限:', input_rps_limit: '請輸入限制',