From 1cd8a49fd4746fda40264581feb31edf8f85c668 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Fri, 18 Jul 2025 16:21:35 +0800 Subject: [PATCH 1/6] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E6=8E=92?= =?UTF-8?q?=E5=BA=8F=E5=8F=82=E6=95=B0=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aspect/SortOrderValidationAspect.java | 4 +-- .../common/utils/SortWhitelistUtil.java | 3 +- .../com/java2nb/system/dao/SysUserDao.java | 35 +++++++++---------- .../aspect/SortOrderValidationAspect.java | 2 +- .../novel/controller/BookController.java | 3 +- .../java2nb/novel/mapper/FrontBookMapper.java | 2 +- .../java/com/java2nb/novel/vo/BookSpVO.java | 6 +++- 7 files changed, 29 insertions(+), 26 deletions(-) diff --git a/novel-admin/src/main/java/com/java2nb/common/aspect/SortOrderValidationAspect.java b/novel-admin/src/main/java/com/java2nb/common/aspect/SortOrderValidationAspect.java index 01da149..846681c 100644 --- a/novel-admin/src/main/java/com/java2nb/common/aspect/SortOrderValidationAspect.java +++ b/novel-admin/src/main/java/com/java2nb/common/aspect/SortOrderValidationAspect.java @@ -25,10 +25,10 @@ import java.util.Map; public class SortOrderValidationAspect { /** - * 拦截所有的mapper方法 + * 拦截mapper的所有list方法 */ @SneakyThrows - @Around("execution(* com.java2nb.*.dao.*Dao.*(..))") + @Around("execution(* com.java2nb.*.dao.*Dao.list*(..))") public Object validateSortAndOrder(ProceedingJoinPoint joinPoint) { Object[] args = joinPoint.getArgs(); MethodSignature signature = (MethodSignature) joinPoint.getSignature(); diff --git a/novel-admin/src/main/java/com/java2nb/common/utils/SortWhitelistUtil.java b/novel-admin/src/main/java/com/java2nb/common/utils/SortWhitelistUtil.java index 2ca8300..d878312 100644 --- a/novel-admin/src/main/java/com/java2nb/common/utils/SortWhitelistUtil.java +++ b/novel-admin/src/main/java/com/java2nb/common/utils/SortWhitelistUtil.java @@ -14,8 +14,7 @@ import java.util.Set; public class SortWhitelistUtil { private final Set allowedColumns = new HashSet<>( - Arrays.asList("id", "name", "create_time", "update_time", "order_num", "last_index_update_time", "word_count", - "visit_count")); + Arrays.asList("id", "name", "order_num")); private final Set allowedOrders = new HashSet<>(Arrays.asList("asc", "desc")); public String sanitizeColumn(String input) { diff --git a/novel-admin/src/main/java/com/java2nb/system/dao/SysUserDao.java b/novel-admin/src/main/java/com/java2nb/system/dao/SysUserDao.java index 1bef4be..92a32ba 100644 --- a/novel-admin/src/main/java/com/java2nb/system/dao/SysUserDao.java +++ b/novel-admin/src/main/java/com/java2nb/system/dao/SysUserDao.java @@ -11,7 +11,6 @@ import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; /** - * * @author xiongxy * @email 1179705413@qq.com * @date 2019-10-03 09:45:11 @@ -19,23 +18,23 @@ import org.apache.ibatis.annotations.Param; @Mapper public interface SysUserDao { - UserDO get(Long userId); - - List list(@ValidateSortOrder Map map); - - int count(Map map); - - int save(UserDO user); - - int update(UserDO user); - - int remove(Long userId); - - int batchRemove(Long[] userIds); - - Long[] listAllDept(); + UserDO get(Long userId); - List listByPerm(Map map); + List list(@ValidateSortOrder Map map); - int countByPerm(Map map); + int count(Map map); + + int save(UserDO user); + + int update(UserDO user); + + int remove(Long userId); + + int batchRemove(Long[] userIds); + + Long[] listAllDept(); + + List listByPerm(@ValidateSortOrder Map map); + + int countByPerm(Map map); } diff --git a/novel-common/src/main/java/com/java2nb/novel/core/aspect/SortOrderValidationAspect.java b/novel-common/src/main/java/com/java2nb/novel/core/aspect/SortOrderValidationAspect.java index 41cb33a..d939471 100644 --- a/novel-common/src/main/java/com/java2nb/novel/core/aspect/SortOrderValidationAspect.java +++ b/novel-common/src/main/java/com/java2nb/novel/core/aspect/SortOrderValidationAspect.java @@ -21,7 +21,7 @@ import java.util.*; * @date 2025/7/17 */ @Aspect -@Component +//@Component @RequiredArgsConstructor public class SortOrderValidationAspect { diff --git a/novel-front/src/main/java/com/java2nb/novel/controller/BookController.java b/novel-front/src/main/java/com/java2nb/novel/controller/BookController.java index 1be8dc3..3d86237 100644 --- a/novel-front/src/main/java/com/java2nb/novel/controller/BookController.java +++ b/novel-front/src/main/java/com/java2nb/novel/controller/BookController.java @@ -15,6 +15,7 @@ import io.github.xxyopen.model.resp.RestResult; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.HashMap; @@ -82,7 +83,7 @@ public class BookController extends BaseController { * 分页搜索 */ @GetMapping("searchByPage") - public RestResult searchByPage(BookSpVO bookSP, @RequestParam(value = "curr", defaultValue = "1") int page, + public RestResult searchByPage(@Validated BookSpVO bookSP, @RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "20") int pageSize) { return RestResult.ok(bookService.searchByPage(bookSP, page, pageSize)); } diff --git a/novel-front/src/main/java/com/java2nb/novel/mapper/FrontBookMapper.java b/novel-front/src/main/java/com/java2nb/novel/mapper/FrontBookMapper.java index 28762b0..e1af572 100644 --- a/novel-front/src/main/java/com/java2nb/novel/mapper/FrontBookMapper.java +++ b/novel-front/src/main/java/com/java2nb/novel/mapper/FrontBookMapper.java @@ -14,7 +14,7 @@ import java.util.List; public interface FrontBookMapper extends BookMapper { - List searchByPage(@ValidateSortOrder BookSpVO params); + List searchByPage(BookSpVO params); void addVisitCount(@Param("bookId") Long bookId, @Param("visitCount") Integer visitCount); diff --git a/novel-front/src/main/java/com/java2nb/novel/vo/BookSpVO.java b/novel-front/src/main/java/com/java2nb/novel/vo/BookSpVO.java index f1a691e..8a7bcc4 100644 --- a/novel-front/src/main/java/com/java2nb/novel/vo/BookSpVO.java +++ b/novel-front/src/main/java/com/java2nb/novel/vo/BookSpVO.java @@ -1,6 +1,7 @@ package com.java2nb.novel.vo; import com.java2nb.novel.core.vo.SortOrderVO; +import jakarta.validation.constraints.Pattern; import lombok.Data; import java.util.Date; @@ -10,7 +11,7 @@ import java.util.Date; * @author 11797 */ @Data -public class BookSpVO extends SortOrderVO { +public class BookSpVO { private String keyword; @@ -30,5 +31,8 @@ public class BookSpVO extends SortOrderVO { private Long updatePeriod; + @Pattern(regexp = "^(last_index_update_time|word_count|visit_count)$") + private String sort; + } From bb1a87e3374acd7ce4e721d2cdd1bbe26fae15db Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Fri, 18 Jul 2025 20:41:00 +0800 Subject: [PATCH 2/6] =?UTF-8?q?chore(sql):=20=E5=86=85=E7=BD=AE=E6=B5=B7?= =?UTF-8?q?=E5=A4=96=E4=B8=93=E7=94=A8=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/sql/novel_plus.sql | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/doc/sql/novel_plus.sql b/doc/sql/novel_plus.sql index 577d3fd..0d15f51 100644 --- a/doc/sql/novel_plus.sql +++ b/doc/sql/novel_plus.sql @@ -3174,4 +3174,43 @@ CREATE TABLE `book_comment_reply` `create_user_id` bigint(20) DEFAULT NULL COMMENT '回复时间', PRIMARY KEY (`id`) ) ENGINE = InnoDB - DEFAULT CHARSET = utf8mb4 COMMENT ='小说评论回复表'; \ No newline at end of file + DEFAULT CHARSET = utf8mb4 COMMENT ='小说评论回复表'; + + +INSERT INTO crawl_source (source_name, crawl_rule, source_status, create_time + , update_time) +VALUES ('飘天文学网(海外专用)', '{ + "bookListUrl": "https://www.piaotia.com/booksort{catId}/{page}.html", + "catIdRule": { + "catId1": "1/0", + "catId2": "2/0", + "catId3": "3/0", + "catId4": "4/0", + "catId5": "6/0", + "catId6": "5/0" + }, + "bookIdPatten": "href=\\"https://www.piaotia.com/bookinfo/(\\\\d+/\\\\d+).html\\"", + "pagePatten": "(\\\\d+)/\\\\d+", + "totalPagePatten": "\\\\d+/(\\\\d+)", + "bookDetailUrl": "https://www.piaotia.com/bookinfo/{bookId}.html", + "bookNamePatten": "

([^/]+)

", + "authorNamePatten": "作    者:([^/]+)<", + "picUrlPatten": "文章状态:([^/]+)", + "bookStatusRule": { + "连载中": 0, + "已完成": 1 + }, + "descStart": " 内容简介:
", + "descEnd": "", + "filterDesc": "", + "bookIndexUrl": "https://www.piaotia.com/html/{bookId}/index.html", + "indexIdPatten": "
  • [^/]+
  • ", + "indexNamePatten": "
  • ([^/]+)
  • ", + "bookContentUrl": "https://www.piaotia.com/html/{bookId}/{indexId}.html", + "contentStart": "
    ", + "contentEnd": "", + "filterContent": "", + "charset": "gbk" +}', 0, '2025-07-13 18:57:39' + , '2025-07-13 18:57:39'); \ No newline at end of file From 8c7b891af2591060d2c1d69f9f390fa318a89d0b Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Fri, 18 Jul 2025 21:24:24 +0800 Subject: [PATCH 3/6] =?UTF-8?q?build(AI):=20Spring=20AI=20=E5=8D=87?= =?UTF-8?q?=E7=BA=A7=E5=88=B0=201.0.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- novel-front/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/novel-front/pom.xml b/novel-front/pom.xml index 3f23ed9..a1f2eea 100644 --- a/novel-front/pom.xml +++ b/novel-front/pom.xml @@ -59,7 +59,7 @@ org.springframework.ai - spring-ai-openai-spring-boot-starter + spring-ai-starter-model-openai diff --git a/pom.xml b/pom.xml index 30c72ac..cc22c38 100644 --- a/pom.xml +++ b/pom.xml @@ -56,7 +56,7 @@ org.springframework.ai spring-ai-bom - 1.0.0-M6 + 1.0.0 pom import From 11d9d6f6e893f841da387ca632a4615d996b165c Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 19 Jul 2025 17:27:21 +0800 Subject: [PATCH 4/6] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E6=8E=92?= =?UTF-8?q?=E5=BA=8F=E5=8F=82=E6=95=B0=E5=A4=84=E7=90=86=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/annotation/SanitizeMap.java | 14 +++ .../common/annotation/ValidateSortOrder.java | 13 --- ...pect.java => MapSortValidationAspect.java} | 27 +++-- .../java/com/java2nb/common/dao/DictDao.java | 4 +- .../java/com/java2nb/common/dao/FileDao.java | 4 +- .../com/java2nb/common/dao/GenColumnsDao.java | 4 +- .../java/com/java2nb/common/dao/LogDao.java | 4 +- .../common/utils/SortWhitelistUtil.java | 38 +++++-- .../com/java2nb/novel/dao/AuthorCodeDao.java | 4 +- .../java/com/java2nb/novel/dao/AuthorDao.java | 4 +- .../com/java2nb/novel/dao/BookCommentDao.java | 4 +- .../com/java2nb/novel/dao/BookContentDao.java | 4 +- .../java/com/java2nb/novel/dao/BookDao.java | 4 +- .../com/java2nb/novel/dao/BookIndexDao.java | 4 +- .../com/java2nb/novel/dao/BookSettingDao.java | 4 +- .../com/java2nb/novel/dao/CategoryDao.java | 4 +- .../com/java2nb/novel/dao/FriendLinkDao.java | 4 +- .../java/com/java2nb/novel/dao/NewsDao.java | 4 +- .../java/com/java2nb/novel/dao/PayDao.java | 4 +- .../java/com/java2nb/novel/dao/UserDao.java | 4 +- .../java2nb/novel/dao/UserFeedbackDao.java | 4 +- .../com/java2nb/novel/dao/WebsiteInfoDao.java | 4 +- .../com/java2nb/system/dao/DataPermDao.java | 4 +- .../java/com/java2nb/system/dao/DeptDao.java | 4 +- .../java/com/java2nb/system/dao/MenuDao.java | 4 +- .../java/com/java2nb/system/dao/RoleDao.java | 4 +- .../java2nb/system/dao/RoleDataPermDao.java | 4 +- .../com/java2nb/system/dao/RoleMenuDao.java | 4 +- .../com/java2nb/system/dao/SysUserDao.java | 7 +- .../com/java2nb/system/dao/UserRoleDao.java | 4 +- .../templates/common/generator/Dao.java.vm | 2 +- .../templates/common/generator/Mapper.java.vm | 2 +- .../core/annotation/ValidateSortOrder.java | 13 --- .../aspect/SortOrderValidationAspect.java | 101 ------------------ .../novel/core/utils/SortWhitelistUtil.java | 28 ----- .../java2nb/novel/core/vo/SortOrderVO.java | 16 --- .../java2nb/novel/mapper/FrontBookMapper.java | 1 - .../java/com/java2nb/novel/vo/BookSpVO.java | 1 - 38 files changed, 116 insertions(+), 247 deletions(-) create mode 100644 novel-admin/src/main/java/com/java2nb/common/annotation/SanitizeMap.java delete mode 100644 novel-admin/src/main/java/com/java2nb/common/annotation/ValidateSortOrder.java rename novel-admin/src/main/java/com/java2nb/common/aspect/{SortOrderValidationAspect.java => MapSortValidationAspect.java} (59%) delete mode 100644 novel-common/src/main/java/com/java2nb/novel/core/annotation/ValidateSortOrder.java delete mode 100644 novel-common/src/main/java/com/java2nb/novel/core/aspect/SortOrderValidationAspect.java delete mode 100644 novel-common/src/main/java/com/java2nb/novel/core/utils/SortWhitelistUtil.java delete mode 100644 novel-common/src/main/java/com/java2nb/novel/core/vo/SortOrderVO.java diff --git a/novel-admin/src/main/java/com/java2nb/common/annotation/SanitizeMap.java b/novel-admin/src/main/java/com/java2nb/common/annotation/SanitizeMap.java new file mode 100644 index 0000000..01594e2 --- /dev/null +++ b/novel-admin/src/main/java/com/java2nb/common/annotation/SanitizeMap.java @@ -0,0 +1,14 @@ +package com.java2nb.common.annotation; + +import java.lang.annotation.*; + +/** + * 标记某个方法参数需要进行 Map 字段的清理和标准化处理。 + * + *

    通常用于 DAO 接口中 list 方法的 Map 参数,用于防止非法排序字段或排序顺序。

    + */ +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface SanitizeMap { +} diff --git a/novel-admin/src/main/java/com/java2nb/common/annotation/ValidateSortOrder.java b/novel-admin/src/main/java/com/java2nb/common/annotation/ValidateSortOrder.java deleted file mode 100644 index 81b55b3..0000000 --- a/novel-admin/src/main/java/com/java2nb/common/annotation/ValidateSortOrder.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.java2nb.common.annotation; - -import java.lang.annotation.*; - -/** - * @author xiongxiaoyang - * @date 2025/7/17 - */ -@Target(ElementType.PARAMETER) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface ValidateSortOrder { -} diff --git a/novel-admin/src/main/java/com/java2nb/common/aspect/SortOrderValidationAspect.java b/novel-admin/src/main/java/com/java2nb/common/aspect/MapSortValidationAspect.java similarity index 59% rename from novel-admin/src/main/java/com/java2nb/common/aspect/SortOrderValidationAspect.java rename to novel-admin/src/main/java/com/java2nb/common/aspect/MapSortValidationAspect.java index 846681c..4065824 100644 --- a/novel-admin/src/main/java/com/java2nb/common/aspect/SortOrderValidationAspect.java +++ b/novel-admin/src/main/java/com/java2nb/common/aspect/MapSortValidationAspect.java @@ -1,6 +1,6 @@ package com.java2nb.common.aspect; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.common.utils.SortWhitelistUtil; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; @@ -16,20 +16,33 @@ import java.util.Arrays; import java.util.Map; /** - * @author xiongxiaoyang - * @date 2025/7/17 + * 拦截所有 Mapper 接口的 list* 方法,对带有 @SanitizeMap 注解的 Map 参数进行排序字段和顺序的规范化处理。 + * + *

    主要防止 SQL 注入或非法排序字段、非法排序顺序的问题。 + * 例如对 sort 和 order 字段进行白名单过滤和标准化处理。

    */ @Aspect @Component @RequiredArgsConstructor -public class SortOrderValidationAspect { +public class MapSortValidationAspect { /** - * 拦截mapper的所有list方法 + * 拦截所有 Mapper 接口的 list* 方法(如 list(), listByPage 等)。 + * 对带有 @SanitizeMap 注解的 Map 参数进行处理。 + * + *

    执行逻辑:

    + *
      + *
    1. 获取方法参数及注解信息
    2. + *
    3. 遍历所有参数,检查是否带有 @SanitizeMap 注解
    4. + *
    5. 如果参数是 Map 类型且有注解,则进行字段清理
    6. + *
    + * + * @param joinPoint 切点信息 + * @return 方法执行结果 */ @SneakyThrows @Around("execution(* com.java2nb.*.dao.*Dao.list*(..))") - public Object validateSortAndOrder(ProceedingJoinPoint joinPoint) { + public Object sanitizeMapParameters(ProceedingJoinPoint joinPoint) { Object[] args = joinPoint.getArgs(); MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); @@ -38,7 +51,7 @@ public class SortOrderValidationAspect { for (int i = 0; i < parameterAnnotations.length; i++) { boolean hasAnnotation = Arrays.stream(parameterAnnotations[i]) - .anyMatch(a -> a.annotationType().equals(ValidateSortOrder.class)); + .anyMatch(a -> a.annotationType().equals(SanitizeMap.class)); if (hasAnnotation && args[i] instanceof Map map) { if (map.get("sort") instanceof String sortStr) { diff --git a/novel-admin/src/main/java/com/java2nb/common/dao/DictDao.java b/novel-admin/src/main/java/com/java2nb/common/dao/DictDao.java index c358fa8..792c3cf 100644 --- a/novel-admin/src/main/java/com/java2nb/common/dao/DictDao.java +++ b/novel-admin/src/main/java/com/java2nb/common/dao/DictDao.java @@ -1,6 +1,6 @@ package com.java2nb.common.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.common.domain.DictDO; import java.util.List; @@ -20,7 +20,7 @@ public interface DictDao { DictDO get(Long id); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/java/com/java2nb/common/dao/FileDao.java b/novel-admin/src/main/java/com/java2nb/common/dao/FileDao.java index 3dec742..604f527 100644 --- a/novel-admin/src/main/java/com/java2nb/common/dao/FileDao.java +++ b/novel-admin/src/main/java/com/java2nb/common/dao/FileDao.java @@ -1,6 +1,6 @@ package com.java2nb.common.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.common.domain.FileDO; import java.util.List; @@ -19,7 +19,7 @@ public interface FileDao { FileDO get(Long id); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/java/com/java2nb/common/dao/GenColumnsDao.java b/novel-admin/src/main/java/com/java2nb/common/dao/GenColumnsDao.java index c5ee927..aa275ad 100644 --- a/novel-admin/src/main/java/com/java2nb/common/dao/GenColumnsDao.java +++ b/novel-admin/src/main/java/com/java2nb/common/dao/GenColumnsDao.java @@ -3,7 +3,7 @@ package com.java2nb.common.dao; import java.util.List; import java.util.Map; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.common.domain.GenColumnsDO; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -20,7 +20,7 @@ public interface GenColumnsDao { GenColumnsDO get(Long id); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/java/com/java2nb/common/dao/LogDao.java b/novel-admin/src/main/java/com/java2nb/common/dao/LogDao.java index 7e3e42a..15d31b5 100644 --- a/novel-admin/src/main/java/com/java2nb/common/dao/LogDao.java +++ b/novel-admin/src/main/java/com/java2nb/common/dao/LogDao.java @@ -1,6 +1,6 @@ package com.java2nb.common.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.common.domain.LogDO; import java.util.List; @@ -19,7 +19,7 @@ public interface LogDao { LogDO get(Long id); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/java/com/java2nb/common/utils/SortWhitelistUtil.java b/novel-admin/src/main/java/com/java2nb/common/utils/SortWhitelistUtil.java index d878312..a6acdec 100644 --- a/novel-admin/src/main/java/com/java2nb/common/utils/SortWhitelistUtil.java +++ b/novel-admin/src/main/java/com/java2nb/common/utils/SortWhitelistUtil.java @@ -2,26 +2,42 @@ package com.java2nb.common.utils; import lombok.experimental.UtilityClass; -import java.util.Arrays; -import java.util.HashSet; import java.util.Set; /** - * @author xiongxiaoyang - * @date 2025/7/17 + * 排序字段和排序顺序的白名单工具类。 */ @UtilityClass public class SortWhitelistUtil { - private final Set allowedColumns = new HashSet<>( - Arrays.asList("id", "name", "order_num")); - private final Set allowedOrders = new HashSet<>(Arrays.asList("asc", "desc")); + // 白名单字段 + private static final Set ALLOWED_COLUMNS = Set.of("id", "name", "order_num"); - public String sanitizeColumn(String input) { - return allowedColumns.contains(input.toLowerCase()) ? input.toLowerCase() : "id"; + // 白名单排序方式 + private static final Set ALLOWED_ORDERS = Set.of("asc", "desc"); + + /** + * 对排序字段进行白名单过滤和标准化。 + * + * @param column 原始字段名 + * @return 安全的字段名,若非法则返回 null + */ + public static String sanitizeColumn(String column) { + if (column == null) return null; + String lower = column.trim().toLowerCase(); + return ALLOWED_COLUMNS.contains(lower) ? lower : null; } - public String sanitizeOrder(String input) { - return allowedOrders.contains(input.toLowerCase()) ? input.toLowerCase() : "asc"; + /** + * 对排序方式进行白名单过滤和标准化。 + * + * @param order 原始排序方式 + * @return 安全的排序方式("asc" 或 "desc"),若非法则返回 null + */ + public static String sanitizeOrder(String order) { + if (order == null) return null; + String lower = order.trim().toLowerCase(); + return ALLOWED_ORDERS.contains(lower) ? lower : null; } + } \ No newline at end of file diff --git a/novel-admin/src/main/java/com/java2nb/novel/dao/AuthorCodeDao.java b/novel-admin/src/main/java/com/java2nb/novel/dao/AuthorCodeDao.java index 2beee31..138e560 100644 --- a/novel-admin/src/main/java/com/java2nb/novel/dao/AuthorCodeDao.java +++ b/novel-admin/src/main/java/com/java2nb/novel/dao/AuthorCodeDao.java @@ -1,6 +1,6 @@ package com.java2nb.novel.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.novel.domain.AuthorCodeDO; @@ -20,7 +20,7 @@ public interface AuthorCodeDao { AuthorCodeDO get(Long id); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/java/com/java2nb/novel/dao/AuthorDao.java b/novel-admin/src/main/java/com/java2nb/novel/dao/AuthorDao.java index 44daeaf..39fe720 100644 --- a/novel-admin/src/main/java/com/java2nb/novel/dao/AuthorDao.java +++ b/novel-admin/src/main/java/com/java2nb/novel/dao/AuthorDao.java @@ -1,6 +1,6 @@ package com.java2nb.novel.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.novel.domain.AuthorDO; import java.util.Date; @@ -20,7 +20,7 @@ public interface AuthorDao { AuthorDO get(Long id); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/java/com/java2nb/novel/dao/BookCommentDao.java b/novel-admin/src/main/java/com/java2nb/novel/dao/BookCommentDao.java index 7350a31..f6838dc 100644 --- a/novel-admin/src/main/java/com/java2nb/novel/dao/BookCommentDao.java +++ b/novel-admin/src/main/java/com/java2nb/novel/dao/BookCommentDao.java @@ -1,6 +1,6 @@ package com.java2nb.novel.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.novel.domain.BookCommentDO; @@ -20,7 +20,7 @@ public interface BookCommentDao { BookCommentDO get(Long id); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/java/com/java2nb/novel/dao/BookContentDao.java b/novel-admin/src/main/java/com/java2nb/novel/dao/BookContentDao.java index 697340d..d070322 100644 --- a/novel-admin/src/main/java/com/java2nb/novel/dao/BookContentDao.java +++ b/novel-admin/src/main/java/com/java2nb/novel/dao/BookContentDao.java @@ -1,6 +1,6 @@ package com.java2nb.novel.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.novel.domain.BookContentDO; import org.apache.ibatis.annotations.Mapper; @@ -20,7 +20,7 @@ public interface BookContentDao { BookContentDO get(Long id); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/java/com/java2nb/novel/dao/BookDao.java b/novel-admin/src/main/java/com/java2nb/novel/dao/BookDao.java index 7ccec2d..14cfcf1 100644 --- a/novel-admin/src/main/java/com/java2nb/novel/dao/BookDao.java +++ b/novel-admin/src/main/java/com/java2nb/novel/dao/BookDao.java @@ -1,6 +1,6 @@ package com.java2nb.novel.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.novel.domain.BookDO; import org.apache.ibatis.annotations.Mapper; @@ -21,7 +21,7 @@ public interface BookDao { BookDO get(Long id); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/java/com/java2nb/novel/dao/BookIndexDao.java b/novel-admin/src/main/java/com/java2nb/novel/dao/BookIndexDao.java index 56e70ff..6a1ecfc 100644 --- a/novel-admin/src/main/java/com/java2nb/novel/dao/BookIndexDao.java +++ b/novel-admin/src/main/java/com/java2nb/novel/dao/BookIndexDao.java @@ -1,6 +1,6 @@ package com.java2nb.novel.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.novel.domain.BookIndexDO; import org.apache.ibatis.annotations.Mapper; @@ -20,7 +20,7 @@ public interface BookIndexDao { BookIndexDO get(Long id); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/java/com/java2nb/novel/dao/BookSettingDao.java b/novel-admin/src/main/java/com/java2nb/novel/dao/BookSettingDao.java index 2cbb02f..3f45786 100644 --- a/novel-admin/src/main/java/com/java2nb/novel/dao/BookSettingDao.java +++ b/novel-admin/src/main/java/com/java2nb/novel/dao/BookSettingDao.java @@ -1,6 +1,6 @@ package com.java2nb.novel.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.novel.domain.BookSettingDO; @@ -20,7 +20,7 @@ public interface BookSettingDao { BookSettingDO get(Long id); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/java/com/java2nb/novel/dao/CategoryDao.java b/novel-admin/src/main/java/com/java2nb/novel/dao/CategoryDao.java index d8c1904..6e9c25d 100644 --- a/novel-admin/src/main/java/com/java2nb/novel/dao/CategoryDao.java +++ b/novel-admin/src/main/java/com/java2nb/novel/dao/CategoryDao.java @@ -1,6 +1,6 @@ package com.java2nb.novel.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.novel.domain.CategoryDO; @@ -20,7 +20,7 @@ public interface CategoryDao { CategoryDO get(Integer id); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/java/com/java2nb/novel/dao/FriendLinkDao.java b/novel-admin/src/main/java/com/java2nb/novel/dao/FriendLinkDao.java index e3698f6..d94d06e 100644 --- a/novel-admin/src/main/java/com/java2nb/novel/dao/FriendLinkDao.java +++ b/novel-admin/src/main/java/com/java2nb/novel/dao/FriendLinkDao.java @@ -1,6 +1,6 @@ package com.java2nb.novel.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.novel.domain.FriendLinkDO; @@ -20,7 +20,7 @@ public interface FriendLinkDao { FriendLinkDO get(Integer id); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/java/com/java2nb/novel/dao/NewsDao.java b/novel-admin/src/main/java/com/java2nb/novel/dao/NewsDao.java index c909ca9..28502c2 100644 --- a/novel-admin/src/main/java/com/java2nb/novel/dao/NewsDao.java +++ b/novel-admin/src/main/java/com/java2nb/novel/dao/NewsDao.java @@ -1,6 +1,6 @@ package com.java2nb.novel.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.novel.domain.NewsDO; @@ -20,7 +20,7 @@ public interface NewsDao { NewsDO get(Long id); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/java/com/java2nb/novel/dao/PayDao.java b/novel-admin/src/main/java/com/java2nb/novel/dao/PayDao.java index acb5aa9..470c45c 100644 --- a/novel-admin/src/main/java/com/java2nb/novel/dao/PayDao.java +++ b/novel-admin/src/main/java/com/java2nb/novel/dao/PayDao.java @@ -1,6 +1,6 @@ package com.java2nb.novel.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.novel.domain.PayDO; @@ -21,7 +21,7 @@ public interface PayDao { PayDO get(Long id); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/java/com/java2nb/novel/dao/UserDao.java b/novel-admin/src/main/java/com/java2nb/novel/dao/UserDao.java index d42d2a4..9b2dd69 100644 --- a/novel-admin/src/main/java/com/java2nb/novel/dao/UserDao.java +++ b/novel-admin/src/main/java/com/java2nb/novel/dao/UserDao.java @@ -1,6 +1,6 @@ package com.java2nb.novel.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.novel.domain.UserDO; import org.apache.ibatis.annotations.Mapper; @@ -19,7 +19,7 @@ public interface UserDao { UserDO get(Long id); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/java/com/java2nb/novel/dao/UserFeedbackDao.java b/novel-admin/src/main/java/com/java2nb/novel/dao/UserFeedbackDao.java index a17eb60..ea742f0 100644 --- a/novel-admin/src/main/java/com/java2nb/novel/dao/UserFeedbackDao.java +++ b/novel-admin/src/main/java/com/java2nb/novel/dao/UserFeedbackDao.java @@ -1,6 +1,6 @@ package com.java2nb.novel.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.novel.domain.UserFeedbackDO; @@ -20,7 +20,7 @@ public interface UserFeedbackDao { UserFeedbackDO get(Long id); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/java/com/java2nb/novel/dao/WebsiteInfoDao.java b/novel-admin/src/main/java/com/java2nb/novel/dao/WebsiteInfoDao.java index 9d646b9..8e8298b 100644 --- a/novel-admin/src/main/java/com/java2nb/novel/dao/WebsiteInfoDao.java +++ b/novel-admin/src/main/java/com/java2nb/novel/dao/WebsiteInfoDao.java @@ -1,6 +1,6 @@ package com.java2nb.novel.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.novel.domain.WebsiteInfoDO; @@ -20,7 +20,7 @@ public interface WebsiteInfoDao { WebsiteInfoDO get(Long id); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/java/com/java2nb/system/dao/DataPermDao.java b/novel-admin/src/main/java/com/java2nb/system/dao/DataPermDao.java index ba2103f..839172f 100644 --- a/novel-admin/src/main/java/com/java2nb/system/dao/DataPermDao.java +++ b/novel-admin/src/main/java/com/java2nb/system/dao/DataPermDao.java @@ -1,6 +1,6 @@ package com.java2nb.system.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.system.domain.DataPermDO; @@ -21,7 +21,7 @@ public interface DataPermDao { DataPermDO get(Long id); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/java/com/java2nb/system/dao/DeptDao.java b/novel-admin/src/main/java/com/java2nb/system/dao/DeptDao.java index c2b11e2..17cf0d6 100644 --- a/novel-admin/src/main/java/com/java2nb/system/dao/DeptDao.java +++ b/novel-admin/src/main/java/com/java2nb/system/dao/DeptDao.java @@ -1,6 +1,6 @@ package com.java2nb.system.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.system.domain.DeptDO; @@ -21,7 +21,7 @@ public interface DeptDao { DeptDO get(Long deptId); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/java/com/java2nb/system/dao/MenuDao.java b/novel-admin/src/main/java/com/java2nb/system/dao/MenuDao.java index 7d6ce8c..ee81e51 100644 --- a/novel-admin/src/main/java/com/java2nb/system/dao/MenuDao.java +++ b/novel-admin/src/main/java/com/java2nb/system/dao/MenuDao.java @@ -1,6 +1,6 @@ package com.java2nb.system.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.system.domain.MenuDO; @@ -20,7 +20,7 @@ public interface MenuDao { MenuDO get(Long menuId); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/java/com/java2nb/system/dao/RoleDao.java b/novel-admin/src/main/java/com/java2nb/system/dao/RoleDao.java index 6e1d425..dd277f6 100644 --- a/novel-admin/src/main/java/com/java2nb/system/dao/RoleDao.java +++ b/novel-admin/src/main/java/com/java2nb/system/dao/RoleDao.java @@ -1,6 +1,6 @@ package com.java2nb.system.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.system.domain.RoleDO; @@ -20,7 +20,7 @@ public interface RoleDao { RoleDO get(Long roleId); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/java/com/java2nb/system/dao/RoleDataPermDao.java b/novel-admin/src/main/java/com/java2nb/system/dao/RoleDataPermDao.java index 5d4eb85..090c018 100644 --- a/novel-admin/src/main/java/com/java2nb/system/dao/RoleDataPermDao.java +++ b/novel-admin/src/main/java/com/java2nb/system/dao/RoleDataPermDao.java @@ -1,6 +1,6 @@ package com.java2nb.system.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.system.domain.RoleDataPermDO; @@ -20,7 +20,7 @@ public interface RoleDataPermDao { RoleDataPermDO get(Long id); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/java/com/java2nb/system/dao/RoleMenuDao.java b/novel-admin/src/main/java/com/java2nb/system/dao/RoleMenuDao.java index 7625a0c..fa91704 100644 --- a/novel-admin/src/main/java/com/java2nb/system/dao/RoleMenuDao.java +++ b/novel-admin/src/main/java/com/java2nb/system/dao/RoleMenuDao.java @@ -1,6 +1,6 @@ package com.java2nb.system.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.system.domain.RoleMenuDO; @@ -20,7 +20,7 @@ public interface RoleMenuDao { RoleMenuDO get(Long id); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/java/com/java2nb/system/dao/SysUserDao.java b/novel-admin/src/main/java/com/java2nb/system/dao/SysUserDao.java index 92a32ba..59dfa5d 100644 --- a/novel-admin/src/main/java/com/java2nb/system/dao/SysUserDao.java +++ b/novel-admin/src/main/java/com/java2nb/system/dao/SysUserDao.java @@ -1,6 +1,6 @@ package com.java2nb.system.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.system.domain.UserDO; @@ -8,7 +8,6 @@ import java.util.List; import java.util.Map; import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; /** * @author xiongxy @@ -20,7 +19,7 @@ public interface SysUserDao { UserDO get(Long userId); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); @@ -34,7 +33,7 @@ public interface SysUserDao { Long[] listAllDept(); - List listByPerm(@ValidateSortOrder Map map); + List listByPerm(@SanitizeMap Map map); int countByPerm(Map map); } diff --git a/novel-admin/src/main/java/com/java2nb/system/dao/UserRoleDao.java b/novel-admin/src/main/java/com/java2nb/system/dao/UserRoleDao.java index 10f385f..0e92e99 100644 --- a/novel-admin/src/main/java/com/java2nb/system/dao/UserRoleDao.java +++ b/novel-admin/src/main/java/com/java2nb/system/dao/UserRoleDao.java @@ -1,6 +1,6 @@ package com.java2nb.system.dao; -import com.java2nb.common.annotation.ValidateSortOrder; +import com.java2nb.common.annotation.SanitizeMap; import com.java2nb.system.domain.UserRoleDO; @@ -21,7 +21,7 @@ public interface UserRoleDao { UserRoleDO get(Long id); - List list(@ValidateSortOrder Map map); + List list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/resources/templates/common/generator/Dao.java.vm b/novel-admin/src/main/resources/templates/common/generator/Dao.java.vm index b3d5f41..69f9518 100644 --- a/novel-admin/src/main/resources/templates/common/generator/Dao.java.vm +++ b/novel-admin/src/main/resources/templates/common/generator/Dao.java.vm @@ -18,7 +18,7 @@ public interface ${className}Dao { ${className}DO get(${pk.javaType} ${pk.attrname}); - List<${className}DO> list(@ValidateSortOrder Map map); + List<${className}DO> list(@SanitizeMap Map map); int count(Map map); diff --git a/novel-admin/src/main/resources/templates/common/generator/Mapper.java.vm b/novel-admin/src/main/resources/templates/common/generator/Mapper.java.vm index ffdbe09..0149899 100644 --- a/novel-admin/src/main/resources/templates/common/generator/Mapper.java.vm +++ b/novel-admin/src/main/resources/templates/common/generator/Mapper.java.vm @@ -44,7 +44,7 @@ public interface ${className}Mapper { "limit #{offset}, #{limit}" + ""+ "") - List<${className}DO> list(@ValidateSortOrder Map map); + List<${className}DO> list(@SanitizeMap Map map); @Select("