From b6e7f88f20686b830771d8c2eaf69d6a6740bd5e Mon Sep 17 00:00:00 2001 From: gaoqr <13665037151@163.com> Date: Fri, 26 Jul 2024 11:07:52 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8A=A5=E8=A1=A8=E5=9F=BA=E7=A1=80=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=EF=BC=9A=E4=BB=A3=E7=A0=81=E8=A7=84=E8=8C=83=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../report/enums/ErrorCodeConstants.java | 16 ++--- .../template/ReportTemplateController.java | 4 +- .../ureport/bean/MockBeanDatasource.java | 29 --------- .../bean/OrderSummaryBeanDatasource.java | 61 ++++++++++--------- .../config/CfReportSpringbeanRegistrar.java | 31 +++++----- .../ReportDatasourceServiceImpl.java | 6 +- .../module/report/util/SqlInjectionUtil.java | 28 +-------- .../ReportDatasetServiceImplTest.java | 2 +- .../ReportDatasourceServiceImplTest.java | 2 +- .../ReportTemplateServiceImplTest.java | 6 +- 10 files changed, 68 insertions(+), 117 deletions(-) delete mode 100644 cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/bean/MockBeanDatasource.java diff --git a/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ErrorCodeConstants.java b/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ErrorCodeConstants.java index 030bcf8a8..539c761cb 100644 --- a/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ErrorCodeConstants.java +++ b/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ErrorCodeConstants.java @@ -11,16 +11,16 @@ import com.cf.imes.framework.common.exception.ErrorCode; public final class ErrorCodeConstants { // ========== UREPORT template模块 1-003-001-000 ========== - public static ErrorCode TEMPLATE_NOT_EXISTS = new ErrorCode(1_003_001_001, "报表模板信息不存在"); + public static final ErrorCode TEMPLATE_NOT_EXISTS = new ErrorCode(1_003_001_001, "报表模板信息不存在"); // ========== UREPORT datasource模块 1-003-002-000 ========== - public static ErrorCode DATASOURCE_NOT_EXISTS = new ErrorCode(1_003_002_001, "报表数据源不存在"); - public static ErrorCode DATASOURCE_CONNECT_FAIL = new ErrorCode(1_003_002_001, "报表数据源连接失败"); + public static final ErrorCode DATASOURCE_NOT_EXISTS = new ErrorCode(1_003_002_001, "报表数据源不存在"); + public static final ErrorCode DATASOURCE_CONNECT_FAIL = new ErrorCode(1_003_002_001, "报表数据源连接失败"); // ========== UREPORT dataset模块 1-003-003-000 ========== - public static ErrorCode DATASET_NOT_EXISTS = new ErrorCode(1_003_003_001, "报表数据集不存在"); - public static ErrorCode DATASET_SQL_INJECTION_RISK = new ErrorCode(1_003_003_002, "存在SQL注入风险"); - public static ErrorCode DATASET_SQL_REQUIRED = new ErrorCode(1_003_003_003, "SQL语句不能为空"); - public static ErrorCode DATASET_SQL_ILLEGAL = new ErrorCode(1_003_003_004, "SQL语句非法"); - public static ErrorCode DATASET_GET_FIELDS_ERROR = new ErrorCode(1_003_003_005, "获取表字段"); + public static final ErrorCode DATASET_NOT_EXISTS = new ErrorCode(1_003_003_001, "报表数据集不存在"); + public static final ErrorCode DATASET_SQL_INJECTION_RISK = new ErrorCode(1_003_003_002, "存在SQL注入风险"); + public static final ErrorCode DATASET_SQL_REQUIRED = new ErrorCode(1_003_003_003, "SQL语句不能为空"); + public static final ErrorCode DATASET_SQL_ILLEGAL = new ErrorCode(1_003_003_004, "SQL语句非法"); + public static final ErrorCode DATASET_GET_FIELDS_ERROR = new ErrorCode(1_003_003_005, "获取表字段"); } diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/ReportTemplateController.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/ReportTemplateController.java index 0f4dec631..9a2c5023c 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/ReportTemplateController.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/ReportTemplateController.java @@ -18,11 +18,11 @@ import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.IOUtils; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; @@ -43,7 +43,7 @@ import static com.cf.imes.framework.common.pojo.CommonResult.success; @Validated @Slf4j public class ReportTemplateController { - @Autowired + @Resource private ReportTemplateService templateService; @PutMapping("/template") diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/bean/MockBeanDatasource.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/bean/MockBeanDatasource.java deleted file mode 100644 index c02c33568..000000000 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/bean/MockBeanDatasource.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.cf.imes.module.report.framework.ureport.bean; - -import com.cf.imes.module.report.framework.ureport.annotation.CfReportSpringbeanDatasource; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * @author Gqr - * @since 2024/7/11 17:15 - */ -@CfReportSpringbeanDatasource(value = "MockBeanDatasource", name = "模拟bean数据源") -public class MockBeanDatasource { - - public List> mockList(String dsName, String datasetName, Map parameters) { - List> testList = new ArrayList<>(); - testList.add(new HashMap() {{ - put("a", "11111"); - put("b", "一一一一一一"); - }}); - testList.add(new HashMap() {{ - put("a", "22222"); - put("b", "二二二二二二"); - }}); - return testList; - } -} diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/bean/OrderSummaryBeanDatasource.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/bean/OrderSummaryBeanDatasource.java index f9f3f6c3e..e013ef8a8 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/bean/OrderSummaryBeanDatasource.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/bean/OrderSummaryBeanDatasource.java @@ -44,6 +44,7 @@ public class OrderSummaryBeanDatasource { * @return */ public List> orderInfo(String dsName, String datasetName, Map parameters) { + log.info("报表数据源[OrderSummaryBeanDatasource][orderInfo][{}][{}]调用开始", dsName, datasetName); List> resultList = new ArrayList<>(); Object orderId = parameters.get(ORDER_ID_FIELD_NAME); @@ -57,20 +58,20 @@ public class OrderSummaryBeanDatasource { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); if (orderDTO != null) { - // 把orderInfo转map并put到resultList中 - resultList.add(new HashMap<>() {{ - // 构造报表所需结构 - put(ORDER_ID_FIELD_NAME, orderDTO.getId()); - put("customOrderNo", orderDTO.getCustomOrderNo()); - put("dealer", orderDTO.getDealer()); - LocalDateTime orderDate = orderDTO.getOrderDate(); - put("orderDate", ObjectUtil.isNotNull(orderDate) ? formatter.format(orderDate) : null); - LocalDateTime deliveryDate = orderDTO.getDeliveryDate(); - put("deliveryDate", ObjectUtil.isNotNull(deliveryDate) ? formatter.format(deliveryDate) : null); - put("customer", orderDTO.getCustomer()); - put("phoneNumber", orderDTO.getPhoneNumber()); - }}); + HashMap resultMap = new HashMap<>(); + // 构造报表所需结构 + resultMap.put(ORDER_ID_FIELD_NAME, orderDTO.getId()); + resultMap.put("customOrderNo", orderDTO.getCustomOrderNo()); + resultMap.put("dealer", orderDTO.getDealer()); + LocalDateTime orderDate = orderDTO.getOrderDate(); + resultMap.put("orderDate", ObjectUtil.isNotNull(orderDate) ? formatter.format(orderDate) : null); + LocalDateTime deliveryDate = orderDTO.getDeliveryDate(); + resultMap.put("deliveryDate", ObjectUtil.isNotNull(deliveryDate) ? formatter.format(deliveryDate) : null); + resultMap.put("customer", orderDTO.getCustomer()); + resultMap.put("phoneNumber", orderDTO.getPhoneNumber()); + resultList.add(resultMap); } + log.info("报表数据源[OrderSummaryBeanDatasource][orderInfo][{}][{}]调用结束", dsName, datasetName); return resultList; } @@ -83,6 +84,7 @@ public class OrderSummaryBeanDatasource { * @return */ public List> orderPlateSummaryByPlate(String dsName, String datasetName, Map parameters) { + log.info("报表数据源[OrderSummaryBeanDatasource][orderPlateSummaryByPlate][{}][{}]调用开始", dsName, datasetName); List> resultList = new ArrayList<>(); Object orderId = parameters.get(ORDER_ID_FIELD_NAME); @@ -92,24 +94,25 @@ public class OrderSummaryBeanDatasource { if (CollUtil.isNotEmpty(plateGoodsRespDTOS)) { plateGoodsRespDTOS.forEach(p -> { - resultList.add(new HashMap<>() {{ - BigDecimal area = p.getArea(); - Integer count = p.getCount(); - // 构造报表所需结构 - put("roomName", p.getRoomName()); - put("bodyName", p.getBodyName()); - put("thickness", p.getThickness()); - put("name", p.getName()); - put("height", p.getHeight()); - put("width", p.getWidth()); - put("count", count); - put("area", area); - put("openDoorType", p.getOpenDoorType()); - put("remark", p.getRemark()); - put("areaAll", area.multiply(BigDecimal.valueOf(count))); - }}); + Map resultMap = new HashMap<>(); + BigDecimal area = p.getArea(); + Integer count = p.getCount(); + // 构造报表所需结构 + resultMap.put("roomName", p.getRoomName()); + resultMap.put("bodyName", p.getBodyName()); + resultMap.put("thickness", p.getThickness()); + resultMap.put("name", p.getName()); + resultMap.put("height", p.getHeight()); + resultMap.put("width", p.getWidth()); + resultMap.put("count", count); + resultMap.put("area", area); + resultMap.put("openDoorType", p.getOpenDoorType()); + resultMap.put("remark", p.getRemark()); + resultMap.put("areaAll", area.multiply(BigDecimal.valueOf(count))); + resultList.add(resultMap); }); } + log.info("报表数据源[OrderSummaryBeanDatasource][orderPlateSummaryByPlate][{}][{}]调用结束", dsName, datasetName); return resultList; } } diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/config/CfReportSpringbeanRegistrar.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/config/CfReportSpringbeanRegistrar.java index 4854d7d04..adf961dc1 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/config/CfReportSpringbeanRegistrar.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/config/CfReportSpringbeanRegistrar.java @@ -31,21 +31,22 @@ public class CfReportSpringbeanRegistrar implements ImportBeanDefinitionRegistra Set candidates = scanner.findCandidateComponents("com.cf.imes.module.report.framework.ureport.bean"); for (BeanDefinition candidate : candidates) { - if (candidate instanceof AnnotatedBeanDefinition) { - AnnotatedBeanDefinition beanDef = (AnnotatedBeanDefinition) candidate; - Map attributes = beanDef.getMetadata().getAnnotationAttributes(CfReportSpringbeanDatasource.class.getName()); - if (attributes != null) { - // 校验注解上的value - String value = (String) attributes.get("value"); - if (!StringUtils.hasText(value)) { - throw new IllegalArgumentException("@CfReportSpringbean requires a non-empty 'value' attribute."); - } - // 校验注解上的name - String name = (String) attributes.get("name"); - if (!StringUtils.hasText(name)) { - throw new IllegalArgumentException("@CfReportSpringbean requires a non-empty 'name' attribute."); - } - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(candidate.getBeanClassName()); + AnnotatedBeanDefinition beanDef = (AnnotatedBeanDefinition) candidate; + Map attributes = beanDef.getMetadata().getAnnotationAttributes(CfReportSpringbeanDatasource.class.getName()); + if (attributes != null) { + // 校验注解上的value + String value = (String) attributes.get("value"); + if (!StringUtils.hasText(value)) { + throw new IllegalArgumentException("@CfReportSpringbean requires a non-empty 'value' attribute."); + } + // 校验注解上的name + String name = (String) attributes.get("name"); + if (!StringUtils.hasText(name)) { + throw new IllegalArgumentException("@CfReportSpringbean requires a non-empty 'name' attribute."); + } + String beanClassName = candidate.getBeanClassName(); + if (StringUtils.hasText(beanClassName)) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(beanClassName); registry.registerBeanDefinition(value, builder.getBeanDefinition()); } } diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/datasource/ReportDatasourceServiceImpl.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/datasource/ReportDatasourceServiceImpl.java index 7a02e5d22..227cefdfc 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/datasource/ReportDatasourceServiceImpl.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/datasource/ReportDatasourceServiceImpl.java @@ -2,6 +2,7 @@ package com.cf.imes.module.report.service.datasource; import cn.hutool.core.annotation.AnnotationUtil; import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.toolkit.sql.SqlInjectionUtils; import com.bstek.ureport.definition.dataset.Field; import com.bstek.ureport.definition.dataset.Parameter; import com.bstek.ureport.definition.dataset.SqlDatasetDefinition; @@ -222,13 +223,14 @@ public class ReportDatasourceServiceImpl implements ReportDatasourceService { } // 获取数据库连接 conn = buildConn(reqVO); - // 校验sql + // 自定义工具校验sql if (SqlInjectionUtil.checkEditSql(sql)) { throw exception(DATASET_SQL_ILLEGAL); } // 检查参数sql注入 for (ReportDatasetParameterVO parameterVO : parameters) { - if (SqlInjectionUtil.checkParam(parameterVO.getDefaultValue())) { + // mybatis-plus util检查参数 + if (SqlInjectionUtils.check(parameterVO.getDefaultValue())) { throw exception(DATASET_SQL_INJECTION_RISK); } } diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/util/SqlInjectionUtil.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/util/SqlInjectionUtil.java index 16326337b..9cd347341 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/util/SqlInjectionUtil.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/util/SqlInjectionUtil.java @@ -16,12 +16,6 @@ public class SqlInjectionUtil { private static final Pattern SQL_EDIT_PATTERN = Pattern.compile("(insert|delete|update|create|drop|truncate|grant|alter|deny|revoke|call|execute|exec|declare|show|rename|set)" + "\\s+.*(into|from|set|where|table|database|view|index|on|cursor|procedure|trigger|for|password|union|and|or)", Pattern.CASE_INSENSITIVE); - /** - * SQL语法检查正则:符合两个关键字(有先后顺序)才算匹配 - */ - private static final Pattern SQL_SYNTAX_PATTERN = Pattern.compile("(insert|delete|update|select|create|drop|truncate|grant|alter|deny|revoke|call|execute|exec|declare|show|rename|set)" + - "\\s+.*(into|from|set|where|table|database|view|index|on|cursor|procedure|trigger|for|password|union|and|or)|(select\\s*\\*\\s*from\\s+)|(and|or)\\s+.*(like|=|>|<|in|between|is|not|exists)", Pattern.CASE_INSENSITIVE); - /** * 使用'、;或注释截断SQL检查正则 */ @@ -38,26 +32,6 @@ public class SqlInjectionUtil { return SQL_COMMENT_PATTERN.matcher(sql).find() || SQL_EDIT_PATTERN.matcher(sql).find(); } - /** - * 检查参数是否存在 SQL 注入 - * - * @param value 检查参数 - * @return true 非法 false 合法 - */ - public static boolean checkParam(String value) { - Objects.requireNonNull(value); - // 处理是否包含SQL注释字符 || 检查是否包含SQL注入敏感字符 - return SQL_COMMENT_PATTERN.matcher(value).find() || SQL_SYNTAX_PATTERN.matcher(value).find(); - } - - /** - * 刪除字段转义符单引号双引号 - * - * @param text 待处理字段 - * @return - */ - public static String removeEscapeCharacter(String text) { - Objects.nonNull(text); - return text.replace("\"", "").replace("'", ""); + private SqlInjectionUtil() { } } diff --git a/cf-module-report/cf-module-report-biz/src/test/java/com/cf/imes/module/report/service/template/ReportDatasetServiceImplTest.java b/cf-module-report/cf-module-report-biz/src/test/java/com/cf/imes/module/report/service/template/ReportDatasetServiceImplTest.java index 336d2ccf9..060a06a64 100644 --- a/cf-module-report/cf-module-report-biz/src/test/java/com/cf/imes/module/report/service/template/ReportDatasetServiceImplTest.java +++ b/cf-module-report/cf-module-report-biz/src/test/java/com/cf/imes/module/report/service/template/ReportDatasetServiceImplTest.java @@ -88,7 +88,7 @@ public class ReportDatasetServiceImplTest extends ReportCommonServiceImplTest{ List datasetList = reportDatasetService.getDatasetList(reqVO); assertNotNull(datasetList); - assertNotEquals(datasetList.size(), 0); + assertNotEquals(0, datasetList.size()); // 删除 reportTemplateService.deleteReportTemplate(templateId); diff --git a/cf-module-report/cf-module-report-biz/src/test/java/com/cf/imes/module/report/service/template/ReportDatasourceServiceImplTest.java b/cf-module-report/cf-module-report-biz/src/test/java/com/cf/imes/module/report/service/template/ReportDatasourceServiceImplTest.java index c9148c430..3301cab06 100644 --- a/cf-module-report/cf-module-report-biz/src/test/java/com/cf/imes/module/report/service/template/ReportDatasourceServiceImplTest.java +++ b/cf-module-report/cf-module-report-biz/src/test/java/com/cf/imes/module/report/service/template/ReportDatasourceServiceImplTest.java @@ -73,7 +73,7 @@ public class ReportDatasourceServiceImplTest extends ReportCommonServiceImplTest List templateDatasourceList = reportDatasourceService.getTemplateDatasourceList(reqVO); assertNotNull(templateDatasourceList); - assertNotEquals(templateDatasourceList.size(),0); + assertNotEquals(0, templateDatasourceList.size()); // 删除 reportTemplateService.deleteReportTemplate(templateId); diff --git a/cf-module-report/cf-module-report-biz/src/test/java/com/cf/imes/module/report/service/template/ReportTemplateServiceImplTest.java b/cf-module-report/cf-module-report-biz/src/test/java/com/cf/imes/module/report/service/template/ReportTemplateServiceImplTest.java index 1608507d1..2fc4a5da7 100644 --- a/cf-module-report/cf-module-report-biz/src/test/java/com/cf/imes/module/report/service/template/ReportTemplateServiceImplTest.java +++ b/cf-module-report/cf-module-report-biz/src/test/java/com/cf/imes/module/report/service/template/ReportTemplateServiceImplTest.java @@ -44,7 +44,7 @@ public class ReportTemplateServiceImplTest extends ReportCommonServiceImplTest { String templateUnZip = template.getContent(); System.out.println("从库中读取template大小:" + templateUnZip.length()); // 校验解压内容是否正确 - assertEquals(JsonUtil.unzipString(templateUnZip),TEMPLATE); + assertEquals(TEMPLATE, JsonUtil.unzipString(templateUnZip)); // 删除 reportTemplateService.deleteReportTemplate(templateId); } @@ -120,8 +120,8 @@ public class ReportTemplateServiceImplTest extends ReportCommonServiceImplTest { List reportTemplateList = reportTemplateService.getReportTemplateList(reqVO); assertNotNull(reportTemplateList); - assertNotEquals(reportTemplateList.size(),0); - assertEquals(reportTemplateList.get(0).getOrganId(),2L); + assertNotEquals(0, reportTemplateList.size()); + assertEquals(2L, reportTemplateList.get(0).getOrganId()); // 删除 reportTemplateService.deleteReportTemplate(templateId);