ai-engineering-init 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/.claude/hooks/skill-forced-eval.js +46 -62
  2. package/.claude/settings.json +10 -1
  3. package/.claude/skills/api-development/SKILL.md +179 -130
  4. package/.claude/skills/architecture-design/SKILL.md +102 -212
  5. package/.claude/skills/backend-annotations/SKILL.md +166 -220
  6. package/.claude/skills/bug-detective/SKILL.md +225 -186
  7. package/.claude/skills/code-patterns/SKILL.md +127 -244
  8. package/.claude/skills/collaborating-with-codex/SKILL.md +96 -113
  9. package/.claude/skills/crud-development/SKILL.md +226 -307
  10. package/.claude/skills/data-permission/SKILL.md +131 -202
  11. package/.claude/skills/database-ops/SKILL.md +158 -355
  12. package/.claude/skills/error-handler/SKILL.md +224 -285
  13. package/.claude/skills/file-oss-management/SKILL.md +174 -169
  14. package/.claude/skills/git-workflow/SKILL.md +123 -341
  15. package/.claude/skills/json-serialization/SKILL.md +121 -137
  16. package/.claude/skills/performance-doctor/SKILL.md +83 -89
  17. package/.claude/skills/redis-cache/SKILL.md +134 -185
  18. package/.claude/skills/scheduled-jobs/SKILL.md +187 -224
  19. package/.claude/skills/security-guard/SKILL.md +168 -276
  20. package/.claude/skills/sms-mail/SKILL.md +266 -228
  21. package/.claude/skills/social-login/SKILL.md +257 -195
  22. package/.claude/skills/tenant-management/SKILL.md +172 -188
  23. package/.claude/skills/utils-toolkit/SKILL.md +214 -222
  24. package/.claude/skills/websocket-sse/SKILL.md +251 -172
  25. package/.claude/skills/workflow-engine/SKILL.md +178 -250
  26. package/.codex/skills/api-development/SKILL.md +179 -130
  27. package/.codex/skills/architecture-design/SKILL.md +102 -212
  28. package/.codex/skills/backend-annotations/SKILL.md +166 -220
  29. package/.codex/skills/bug-detective/SKILL.md +225 -186
  30. package/.codex/skills/code-patterns/SKILL.md +127 -244
  31. package/.codex/skills/collaborating-with-codex/SKILL.md +96 -113
  32. package/.codex/skills/crud-development/SKILL.md +226 -307
  33. package/.codex/skills/data-permission/SKILL.md +131 -202
  34. package/.codex/skills/database-ops/SKILL.md +158 -355
  35. package/.codex/skills/error-handler/SKILL.md +224 -285
  36. package/.codex/skills/file-oss-management/SKILL.md +174 -169
  37. package/.codex/skills/git-workflow/SKILL.md +123 -341
  38. package/.codex/skills/json-serialization/SKILL.md +121 -137
  39. package/.codex/skills/performance-doctor/SKILL.md +83 -89
  40. package/.codex/skills/redis-cache/SKILL.md +134 -185
  41. package/.codex/skills/scheduled-jobs/SKILL.md +187 -224
  42. package/.codex/skills/security-guard/SKILL.md +168 -276
  43. package/.codex/skills/sms-mail/SKILL.md +266 -228
  44. package/.codex/skills/social-login/SKILL.md +257 -195
  45. package/.codex/skills/tenant-management/SKILL.md +172 -188
  46. package/.codex/skills/utils-toolkit/SKILL.md +214 -222
  47. package/.codex/skills/websocket-sse/SKILL.md +251 -172
  48. package/.codex/skills/workflow-engine/SKILL.md +178 -250
  49. package/.cursor/hooks/cursor-skill-eval.js +66 -6
  50. package/.cursor/skills/api-development/SKILL.md +179 -130
  51. package/.cursor/skills/architecture-design/SKILL.md +102 -212
  52. package/.cursor/skills/backend-annotations/SKILL.md +166 -220
  53. package/.cursor/skills/bug-detective/SKILL.md +225 -186
  54. package/.cursor/skills/code-patterns/SKILL.md +127 -244
  55. package/.cursor/skills/collaborating-with-codex/SKILL.md +96 -113
  56. package/.cursor/skills/crud-development/SKILL.md +226 -307
  57. package/.cursor/skills/data-permission/SKILL.md +131 -202
  58. package/.cursor/skills/database-ops/SKILL.md +158 -355
  59. package/.cursor/skills/error-handler/SKILL.md +224 -285
  60. package/.cursor/skills/file-oss-management/SKILL.md +174 -169
  61. package/.cursor/skills/git-workflow/SKILL.md +123 -341
  62. package/.cursor/skills/json-serialization/SKILL.md +121 -137
  63. package/.cursor/skills/performance-doctor/SKILL.md +83 -89
  64. package/.cursor/skills/redis-cache/SKILL.md +134 -185
  65. package/.cursor/skills/scheduled-jobs/SKILL.md +187 -224
  66. package/.cursor/skills/security-guard/SKILL.md +168 -276
  67. package/.cursor/skills/sms-mail/SKILL.md +266 -228
  68. package/.cursor/skills/social-login/SKILL.md +257 -195
  69. package/.cursor/skills/tenant-management/SKILL.md +172 -188
  70. package/.cursor/skills/utils-toolkit/SKILL.md +214 -222
  71. package/.cursor/skills/websocket-sse/SKILL.md +251 -172
  72. package/.cursor/skills/workflow-engine/SKILL.md +178 -250
  73. package/AGENTS.md +49 -540
  74. package/CLAUDE.md +73 -119
  75. package/README.md +37 -6
  76. package/bin/index.js +5 -1
  77. package/package.json +1 -1
  78. package/src/skills/api-development/SKILL.md +179 -130
  79. package/src/skills/architecture-design/SKILL.md +102 -212
  80. package/src/skills/backend-annotations/SKILL.md +166 -220
  81. package/src/skills/bug-detective/SKILL.md +225 -186
  82. package/src/skills/code-patterns/SKILL.md +127 -244
  83. package/src/skills/collaborating-with-codex/SKILL.md +96 -113
  84. package/src/skills/crud-development/SKILL.md +226 -307
  85. package/src/skills/data-permission/SKILL.md +131 -202
  86. package/src/skills/database-ops/SKILL.md +158 -355
  87. package/src/skills/error-handler/SKILL.md +224 -285
  88. package/src/skills/file-oss-management/SKILL.md +174 -169
  89. package/src/skills/git-workflow/SKILL.md +123 -341
  90. package/src/skills/json-serialization/SKILL.md +121 -137
  91. package/src/skills/performance-doctor/SKILL.md +83 -89
  92. package/src/skills/redis-cache/SKILL.md +134 -185
  93. package/src/skills/scheduled-jobs/SKILL.md +187 -224
  94. package/src/skills/security-guard/SKILL.md +168 -276
  95. package/src/skills/sms-mail/SKILL.md +266 -228
  96. package/src/skills/social-login/SKILL.md +257 -195
  97. package/src/skills/tenant-management/SKILL.md +172 -188
  98. package/src/skills/utils-toolkit/SKILL.md +214 -222
  99. package/src/skills/websocket-sse/SKILL.md +251 -172
  100. package/src/skills/workflow-engine/SKILL.md +178 -250
  101. package/.claude/skills/skill-creator/LICENSE.txt +0 -202
  102. package/.claude/skills/skill-creator/SKILL.md +0 -479
  103. package/.claude/skills/skill-creator/agents/analyzer.md +0 -274
  104. package/.claude/skills/skill-creator/agents/comparator.md +0 -202
  105. package/.claude/skills/skill-creator/agents/grader.md +0 -223
  106. package/.claude/skills/skill-creator/assets/eval_review.html +0 -146
  107. package/.claude/skills/skill-creator/eval-viewer/generate_review.py +0 -471
  108. package/.claude/skills/skill-creator/eval-viewer/viewer.html +0 -1325
  109. package/.claude/skills/skill-creator/references/schemas.md +0 -430
  110. package/.claude/skills/skill-creator/scripts/__init__.py +0 -0
  111. package/.claude/skills/skill-creator/scripts/aggregate_benchmark.py +0 -401
  112. package/.claude/skills/skill-creator/scripts/generate_report.py +0 -326
  113. package/.claude/skills/skill-creator/scripts/improve_description.py +0 -248
  114. package/.claude/skills/skill-creator/scripts/package_skill.py +0 -136
  115. package/.claude/skills/skill-creator/scripts/quick_validate.py +0 -103
  116. package/.claude/skills/skill-creator/scripts/run_eval.py +0 -310
  117. package/.claude/skills/skill-creator/scripts/run_loop.py +0 -332
  118. package/.claude/skills/skill-creator/scripts/utils.py +0 -47
@@ -1,353 +1,245 @@
1
1
  ---
2
2
  name: security-guard
3
3
  description: |
4
- 后端安全开发规范。包含 Sa-Token 认证授权、数据脱敏、数据加密、接口安全、漏洞防护。
5
-
4
+ 通用后端安全开发指南。包含认证授权模式对比、输入校验、XSS/SQL注入防护、数据脱敏加密、安全检查清单。
6
5
  触发场景:
7
- - Sa-Token 权限控制配置
8
- - 登录认证、Token 管理
9
- - 数据脱敏处理(@Sensitive)
10
- - 数据加密处理(@EncryptField、@ApiEncrypt)
11
- - 接口限流(@RateLimiter)
12
- - 防重复提交(@RepeatSubmit)
13
- - XSS/SQL注入防护
14
-
15
- 触发词:安全、Sa-Token、@SaCheckPermission、@SaCheckLogin、@SaCheckRole、登录认证、Token、数据脱敏、@Sensitive、加密解密、@EncryptField、@ApiEncrypt、限流、@RateLimiter、防重复、@RepeatSubmit、XSS、SQL注入、漏洞防护、敏感数据、LoginHelper
16
-
17
- 注意:
18
- - 如需行级数据权限(@DataPermission、部门隔离),请使用 data-permission。
19
- - 如果是设计异常处理机制(try-catch、错误码),请使用 error-handler。
6
+ - 设计认证授权方案
7
+ - 配置权限校验
8
+ - 防护 XSS / SQL 注入
9
+ - 数据脱敏 / 加密处理
10
+ - 安全合规审查
11
+ 触发词:安全、认证、授权、权限、Token、登录、XSS、SQL注入、脱敏、加密、RBAC、OAuth、CORS、漏洞防护
12
+ 注意:如果项目有专属技能(如 `leniu-security-guard`),优先使用专属版本。
20
13
  ---
21
14
 
22
- # 后端安全开发指南
23
-
24
- > 本项目是纯后端项目,本文档专注于 Java 后端安全规范。
25
-
26
- ## 1. Sa-Token 认证授权
27
-
28
- ### 1.1 权限注解
29
-
30
- ```java
31
- import cn.dev33.satoken.annotation.*;
32
-
33
- @SaCheckLogin // 登录校验
34
- @SaCheckPermission("system:user:add") // 权限校验
35
- @SaCheckRole("admin") // 角色校验
36
- @SaCheckSafe // 二级认证(敏感操作)
37
-
38
- // 多权限(满足其一 / 全部满足)
39
- @SaCheckPermission(value = {"system:user:add", "system:user:update"}, mode = SaMode.OR)
40
- @SaCheckPermission(value = {"system:user:add", "system:user:update"}, mode = SaMode.AND)
41
-
42
- // 多角色(满足其一)
43
- @SaCheckRole(value = {"admin", "editor"}, mode = SaMode.OR)
44
- ```
45
-
46
- ### 1.2 LoginHelper 工具类
47
-
48
- > 位置:`ruoyi-common-satoken/.../utils/LoginHelper.java`
15
+ # 安全开发指南
49
16
 
50
- ```java
51
- import org.dromara.common.satoken.utils.LoginHelper;
52
-
53
- // 用户信息
54
- LoginUser user = LoginHelper.getLoginUser();
55
- Long userId = LoginHelper.getUserId();
56
- String name = LoginHelper.getUsername();
57
- String tenant = LoginHelper.getTenantId();
58
- Long deptId = LoginHelper.getDeptId();
59
-
60
- // 管理员判断
61
- LoginHelper.isSuperAdmin(); // userId = 1
62
- LoginHelper.isTenantAdmin(); // 租户管理员
63
- LoginHelper.isLogin(); // 是否已登录
64
-
65
- // 用户类型 & 登录
66
- UserType type = LoginHelper.getUserType();
67
- LoginHelper.login(loginUser, loginParameter);
68
- ```
17
+ > 通用模板。如果项目有专属技能(如 `leniu-security-guard`),优先使用。
69
18
 
70
- ### 1.3 角色与权限常量
19
+ ## 设计原则
71
20
 
72
- | 常量 | 值 | 说明 |
73
- |------|-----|------|
74
- | 超级管理员角色 | `superadmin` | 拥有所有权限 |
75
- | 租户管理员角色 | `admin` | 租户内所有权限 |
76
- | 通配符权限 | `*:*:*` | 所有权限标识 |
77
- | 超级管理员ID | `1L` | 系统超管用户ID |
21
+ 1. **纵深防御**:不依赖单一安全机制,从传输层、认证层、授权层、数据层多维度防护。
22
+ 2. **最小权限**:默认拒绝,显式授权。每个接口必须声明所需权限。
23
+ 3. **输入不可信**:所有外部输入(用户参数、请求头、Cookie)必须校验后使用。
24
+ 4. **敏感数据保护**:存储加密、传输加密、展示脱敏,三层保护。
25
+ 5. **审计可追溯**:关键操作记录日志,包含操作人、操作时间、操作内容。
78
26
 
79
27
  ---
80
28
 
81
- ## 2. 数据脱敏(@Sensitive)
82
-
83
- > 位置:`ruoyi-common-sensitive/.../`
84
- > 完整 17 种策略详见 `references/sensitive-strategies.md`
85
-
86
- ### 基本用法
87
-
88
- ```java
89
- import org.dromara.common.sensitive.annotation.Sensitive;
90
- import org.dromara.common.sensitive.core.SensitiveStrategy;
91
-
92
- public class UserVo {
93
- @Sensitive(strategy = SensitiveStrategy.PHONE) // 138****8888
94
- private String phone;
95
-
96
- @Sensitive(strategy = SensitiveStrategy.ID_CARD) // 110***********1234
97
- private String idCard;
98
-
99
- @Sensitive(strategy = SensitiveStrategy.EMAIL) // t**@example.com
100
- private String email;
101
-
102
- @Sensitive(strategy = SensitiveStrategy.BANK_CARD) // 6222***********1234
103
- private String bankCard;
29
+ ## 认证授权方案对比
104
30
 
105
- @Sensitive(strategy = SensitiveStrategy.CHINESE_NAME) // 张*
106
- private String realName;
107
-
108
- @Sensitive(strategy = SensitiveStrategy.PASSWORD) // ******
109
- private String password;
110
- }
111
- ```
112
-
113
- ### 基于角色/权限的脱敏控制
114
-
115
- ```java
116
- // admin 角色可查看原数据,其他用户看脱敏数据
117
- @Sensitive(strategy = SensitiveStrategy.ID_CARD, roleKey = {"admin"})
118
- private String idCard;
119
-
120
- // 需要权限才能看原数据
121
- @Sensitive(strategy = SensitiveStrategy.PHONE, perms = {"system:user:detail"})
122
- private String phone;
123
-
124
- // roleKey 和 perms 是 OR 关系
125
- @Sensitive(strategy = SensitiveStrategy.BANK_CARD,
126
- roleKey = {"admin"}, perms = {"finance:account:query"})
127
- private String bankCard;
128
- ```
129
-
130
- ### 日志脱敏
131
-
132
- ```java
133
- // NG: log.info("手机号: {}", phone);
134
- // OK:
135
- log.info("手机号: {}", DesensitizedUtil.mobilePhone(phone));
136
- ```
31
+ | 维度 | Spring Security | Apache Shiro | Sa-Token |
32
+ |------|----------------|-------------|----------|
33
+ | 学习曲线 | 陡峭 | 中等 | 平缓 |
34
+ | 功能丰富度 | 最全面 | 基础够用 | 功能丰富 |
35
+ | Spring 集成 | 原生集成 | 需适配 | 自动配置 |
36
+ | OAuth2 支持 | 原生支持 | 需扩展 | 内置 SSO |
37
+ | 微服务支持 | 优秀 | 一般 | 良好 |
38
+ | 适用场景 | 企业级、复杂权限 | 轻量项目 | 快速开发 |
137
39
 
138
40
  ---
139
41
 
140
- ## 3. 数据加密(@EncryptField / @ApiEncrypt)
141
-
142
- > 位置:`ruoyi-common-encrypt/.../`
143
- > 完整加密配置和工具类详见 `references/encrypt-config.md`
42
+ ## 实现模式
144
43
 
145
- ### 支持算法
146
-
147
- | 算法 | 类型 | 密钥要求 |
148
- |------|------|---------|
149
- | BASE64 | 编码 | 无 |
150
- | AES | 对称加密 | 16/24/32 位 |
151
- | RSA | 非对称加密 | 公钥/私钥 |
152
- | SM2 | 国密非对称 | 公钥/私钥 |
153
- | SM4 | 国密对称 | 16 位 |
154
-
155
- ### 字段级加密
44
+ ### 1. 认证(Authentication)
156
45
 
157
46
  ```java
158
- import org.dromara.common.encrypt.annotation.EncryptField;
159
- import org.dromara.common.encrypt.enumd.AlgorithmType;
160
-
161
- public class User {
162
- @EncryptField // 默认(全局配置)
163
- private String password;
164
-
165
- @EncryptField(algorithm = AlgorithmType.AES) // AES
166
- private String idCard;
167
-
168
- @EncryptField(algorithm = AlgorithmType.SM4) // SM4 国密
169
- private String phone;
47
+ // 方式一:注解式认证(框架无关的概念)
48
+ @[你的认证注解] // 登录校验
49
+ @[你的权限注解]("system:user:add") // 权限校验
50
+ @[你的角色注解]("admin") // 角色校验
51
+
52
+ // 方式二:编程式认证
53
+ @RestController
54
+ public class UserController {
55
+
56
+ @Autowired
57
+ private [你的安全工具类] securityUtils;
58
+
59
+ @GetMapping("/profile")
60
+ public Result<?> profile() {
61
+ // 获取当前登录用户
62
+ Long userId = securityUtils.getCurrentUserId();
63
+ String username = securityUtils.getCurrentUsername();
64
+ boolean isAdmin = securityUtils.hasRole("admin");
65
+ boolean hasPerm = securityUtils.hasPermission("system:user:list");
66
+
67
+ if (!securityUtils.isAuthenticated()) {
68
+ throw new [你的异常类]("未登录");
69
+ }
70
+ // ...
71
+ }
170
72
  }
171
73
  ```
172
74
 
173
- ### API 级加密
75
+ ### 2. 授权模型(RBAC)
174
76
 
175
- ```java
176
- import org.dromara.common.encrypt.annotation.ApiEncrypt;
177
-
178
- @ApiEncrypt // 请求体自动解密
179
- @PostMapping("/addUser")
180
- public R<Long> addUser(@RequestBody UserBo bo) { }
181
-
182
- @ApiEncrypt(response = true) // 请求解密 + 响应加密
183
- @PostMapping("/updateUser")
184
- public R<Void> updateUser(@RequestBody UserBo bo) { }
185
77
  ```
78
+ 用户 (User)
79
+ └── 角色 (Role) -- 多对多
80
+ └── 权限 (Permission) -- 多对多
81
+ └── 菜单/按钮/API
186
82
 
187
- ---
188
-
189
- ## 4. 接口限流(@RateLimiter)
190
-
191
- > 位置:`ruoyi-common-ratelimiter/.../`
83
+ 权限标识格式:模块:资源:操作
84
+ 示例:system:user:add, order:info:export
85
+ ```
192
86
 
193
87
  ```java
194
- import org.dromara.common.ratelimiter.annotation.RateLimiter;
195
- import org.dromara.common.ratelimiter.enums.LimitType;
196
-
197
- // 全局限流:60秒内最多100次
198
- @RateLimiter(time = 60, count = 100)
199
-
200
- // IP 限流:每个 IP 每分钟最多10次
201
- @RateLimiter(time = 60, count = 10, limitType = LimitType.IP)
202
-
203
- // 动态 key(SpEL)
204
- @RateLimiter(key = "#userId", time = 60, count = 5)
205
-
206
- // 自定义错误消息
207
- @RateLimiter(time = 60, count = 10, message = "访问过于频繁,请稍后再试")
88
+ // 多权限校验(满足其一 / 全部满足)
89
+ @RequiresPermissions(value = {"system:user:add", "system:user:edit"}, logical = Logical.OR)
90
+ @RequiresPermissions(value = {"system:user:add", "system:user:edit"}, logical = Logical.AND)
208
91
 
209
- // 集群限流
210
- @RateLimiter(time = 60, count = 1000, limitType = LimitType.CLUSTER)
92
+ // 多角色校验
93
+ @RequiresRoles(value = {"admin", "editor"}, logical = Logical.OR)
211
94
  ```
212
95
 
213
- ### 推荐配置
214
-
215
- | 场景 | time | count | limitType |
216
- |------|------|-------|-----------|
217
- | 登录接口 | 60 | 5-10 | IP |
218
- | 验证码 | 60 | 3 | IP |
219
- | 查询接口 | 60 | 100-1000 | DEFAULT |
220
- | 写入接口 | 60 | 10-50 | DEFAULT |
221
- | 敏感操作 | 60 | 1-5 | IP |
222
-
223
- ---
224
-
225
- ## 5. 防重复提交(@RepeatSubmit)
226
-
227
- > 位置:`ruoyi-common-idempotent/.../`
96
+ ### 3. 输入校验
228
97
 
229
98
  ```java
230
- import org.dromara.common.idempotent.annotation.RepeatSubmit;
231
-
232
- @RepeatSubmit() // 默认 5 秒
233
- @RepeatSubmit(interval = 10, timeUnit = TimeUnit.SECONDS) // 10 秒
234
- @RepeatSubmit(interval = 5000, message = "请勿重复提交订单") // 自定义消息
235
- ```
99
+ public class UserDTO {
100
+ @NotNull(message = "ID不能为空", groups = {UpdateGroup.class})
101
+ private Long id;
236
102
 
237
- | 场景 | 推荐间隔 |
238
- |------|---------|
239
- | 普通表单 | 3-5 |
240
- | 订单创建 | 10 秒 |
241
- | 支付操作 | 30 秒 |
242
- | 文件上传 | 10 秒 |
103
+ @NotBlank(message = "用户名不能为空")
104
+ @Size(min = 2, max = 20, message = "用户名长度2-20")
105
+ @Pattern(regexp = "^[a-zA-Z0-9_]+$", message = "只能包含字母数字下划线")
106
+ private String username;
243
107
 
244
- ---
108
+ @Email(message = "邮箱格式不正确")
109
+ private String email;
245
110
 
246
- ## 6. 数据权限(@DataPermission)
111
+ @Min(value = 0, message = "年龄不能为负")
112
+ @Max(value = 150, message = "年龄超出范围")
113
+ private Integer age;
114
+ }
247
115
 
248
- > **完整指南请使用 `data-permission` 技能**
116
+ // Controller 分组校验
117
+ @PostMapping
118
+ public Result<?> add(@Validated(AddGroup.class) @RequestBody UserDTO dto) { }
249
119
 
250
- ```java
251
- @DataPermission({
252
- @DataColumn(key = "deptName", value = "create_dept"),
253
- @DataColumn(key = "userName", value = "create_by")
254
- })
255
- public TableDataInfo<OrderVo> pageWithPermission(OrderBo bo, PageQuery pageQuery) { }
120
+ @PutMapping
121
+ public Result<?> update(@Validated(UpdateGroup.class) @RequestBody UserDTO dto) { }
256
122
  ```
257
123
 
258
- 权限类型:全部数据 | 本部门 | 本部门及以下 | 仅本人 | 自定义
259
-
260
- ---
261
-
262
- ## 7. 输入校验
124
+ ### 4. 越权访问防护
263
125
 
264
126
  ```java
265
- import org.dromara.common.core.validate.AddGroup;
266
- import org.dromara.common.core.validate.EditGroup;
267
-
268
- public class UserBo {
269
- @NotNull(message = "ID不能为空", groups = { EditGroup.class })
270
- private Long id;
271
-
272
- @NotBlank(message = "用户名不能为空", groups = { AddGroup.class, EditGroup.class })
273
- @Size(min = 2, max = 20)
274
- @Pattern(regexp = "^[a-zA-Z0-9_]+$", message = "只能包含字母数字下划线")
275
- private String username;
127
+ public [你的VO类] selectById(Long id) {
128
+ var entity = baseMapper.selectById(id);
129
+ if (entity == null) {
130
+ throw new [你的异常类]("数据不存在");
131
+ }
132
+ // 非管理员只能访问自己的数据
133
+ Long currentUserId = [你的安全工具类].getCurrentUserId();
134
+ if (![你的安全工具类].isAdmin() && !entity.getCreatedBy().equals(currentUserId)) {
135
+ throw new [你的异常类]("无权访问此数据");
136
+ }
137
+ return convertToVo(entity);
276
138
  }
277
-
278
- // Controller 分组校验
279
- @PostMapping public R<Long> add(@Validated(AddGroup.class) @RequestBody UserBo bo) { }
280
- @PutMapping public R<Void> update(@Validated(EditGroup.class) @RequestBody UserBo bo) { }
281
139
  ```
282
140
 
283
141
  ---
284
142
 
285
- ## 8. 常见漏洞防护
143
+ ## 常见漏洞防护
286
144
 
287
145
  ### SQL 注入
288
146
 
289
147
  ```java
290
- // NG: "SELECT * FROM user WHERE name = '" + name + "'"
291
- // NG: @Select("SELECT * FROM user WHERE name = '${name}'")
292
- // OK: MyBatis-Plus LambdaQueryWrapper
293
- // OK: @Select("SELECT * FROM user WHERE name = #{name}")
148
+ // 禁止:字符串拼接 SQL
149
+ "SELECT * FROM user WHERE name = '" + name + "'"
150
+ @Select("SELECT * FROM user WHERE name = '${name}'")
151
+
152
+ // 正确:参数化查询
153
+ @Select("SELECT * FROM user WHERE name = #{name}")
154
+ // 或使用 ORM 框架的 QueryWrapper / LambdaQueryWrapper
294
155
  ```
295
156
 
296
- ### 越权访问
157
+ ### XSS 防护
297
158
 
298
159
  ```java
299
- @Override
300
- public OrderVo selectById(Long id) {
301
- Order order = baseMapper.selectById(id);
302
- if (ObjectUtil.isNull(order)) {
303
- throw new ServiceException("订单不存在");
304
- }
305
- if (!LoginHelper.isSuperAdmin() && !order.getUserId().equals(LoginHelper.getUserId())) {
306
- throw new ServiceException("无权访问此订单");
307
- }
308
- return MapstructUtils.convert(order, OrderVo.class);
160
+ // 方式一:全局 Filter(推荐)
161
+ @Bean
162
+ public FilterRegistrationBean<XssFilter> xssFilter() {
163
+ FilterRegistrationBean<XssFilter> registration = new FilterRegistrationBean<>();
164
+ registration.setFilter(new XssFilter());
165
+ registration.addUrlPatterns("/*");
166
+ registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
167
+ return registration;
309
168
  }
310
169
 
311
- // 批量操作同样校验归属
170
+ // 方式二:手动转义
171
+ String safe = HtmlUtils.htmlEscape(userInput);
172
+ String safe = StringEscapeUtils.escapeHtml4(userInput);
312
173
  ```
313
174
 
314
175
  ### 敏感信息泄露
315
176
 
316
177
  ```java
317
- // NG: return userDao.getById(id); // 包含密码等
318
- // OK: return MapstructUtils.convert(user, UserVo.class); // VO 过滤敏感字段
319
- // OK: 使用 @Sensitive 自动脱敏
178
+ // 禁止:直接返回 Entity(可能包含密码等)
179
+ return userDao.getById(id);
180
+
181
+ // 正确:使用 VO 过滤 + @Sensitive 脱敏
182
+ UserVo vo = new UserVo();
183
+ BeanUtils.copyProperties(user, vo);
184
+ return vo;
185
+
186
+ // 日志脱敏
187
+ log.info("手机号: {}", DesensitizedUtil.mobilePhone(phone));
320
188
  ```
321
189
 
322
190
  ---
323
191
 
324
- ## 9. 安全检查清单
192
+ ## 安全检查清单
325
193
 
326
194
  ### 代码审查
327
195
 
328
- - [ ] 用户输入经过 `@NotBlank`/`@Size`/`@Pattern` 校验
329
- - [ ] SQL 使用 MyBatis-Plus 或参数化查询(#{}
330
- - [ ] 敏感字段使用 `@Sensitive` 脱敏
331
- - [ ] 需加密字段使用 `@EncryptField`
332
- - [ ] Controller 添加 `@SaCheckPermission`
333
- - [ ] 敏感操作添加 `@RepeatSubmit`
334
- - [ ] 高频接口添加 `@RateLimiter`
196
+ - [ ] 用户输入经过 `@NotBlank` / `@Size` / `@Pattern` 校验
197
+ - [ ] SQL 使用参数化查询(`#{}` 而非 `${}`)
198
+ - [ ] 敏感字段使用脱敏注解或 VO 过滤
199
+ - [ ] 存储敏感数据使用加密
200
+ - [ ] Controller 添加权限注解
201
+ - [ ] 写入接口添加防重复提交
202
+ - [ ] 高频接口添加限流
335
203
  - [ ] 批量操作校验数据归属(防越权)
336
- - [ ] 文件上传校验类型/大小/扩展名
204
+ - [ ] 文件上传校验类型 / 大小 / 扩展名(白名单)
337
205
  - [ ] 日志中无敏感信息(或已脱敏)
338
206
 
339
- ### 配置 & 部署
207
+ ### 配置与部署
340
208
 
341
- - [ ] 生产关闭调试模式
342
- - [ ] 敏感配置已加密或使用环境变量
209
+ - [ ] 生产环境关闭调试模式、Swagger
210
+ - [ ] 敏感配置使用环境变量或配置中心加密
343
211
  - [ ] Token 有效期合理(2-24h)
344
- - [ ] CORS 不使用 `*`
345
- - [ ] 启用 HTTPS、安全响应头
346
- - [ ] 错误页不泄露堆栈、数据库/Redis 端口不对外
212
+ - [ ] CORS 不使用 `*`,限定域名
213
+ - [ ] 启用 HTTPS
214
+ - [ ] 设置安全响应头(X-Frame-Options、X-Content-Type-Options、CSP)
215
+ - [ ] 错误页不泄露堆栈信息
216
+ - [ ] 数据库 / Redis 端口不对外暴露
347
217
 
348
218
  ---
349
219
 
350
- ## 注意事项
220
+ ## 常见错误
221
+
222
+ ```java
223
+ // 1. 忘记加认证注解,接口裸奔
224
+ @GetMapping("/users")
225
+ public Result<?> list() { ... } // 任何人可访问!
351
226
 
352
- - leniu-tengyun-core 项目请使用 `leniu-security-guard` skill
353
- - leniu 使用自研 secure 模块,注解和工具类与 RuoYi-Vue-Plus 不同
227
+ // 2. 只校验前端,不校验后端
228
+ // 前端限制了输入范围,但后端不做校验 -> 可被绕过
229
+
230
+ // 3. 用 Map 传递用户信息(类型不安全)
231
+ Map<String, Object> user = getCurrentUser(); // 缺乏类型约束
232
+ // 应使用强类型 LoginUser 对象
233
+
234
+ // 4. 密码明文存储
235
+ user.setPassword(rawPassword);
236
+ // 应使用 BCrypt / SCrypt 哈希
237
+ user.setPassword(passwordEncoder.encode(rawPassword));
238
+
239
+ // 5. Token 存储敏感信息
240
+ // JWT payload 不应包含密码、完整身份证号等
241
+
242
+ // 6. CORS 配置过于宽松
243
+ .allowedOrigins("*").allowedMethods("*").allowCredentials(true)
244
+ // allowedOrigins("*") 与 allowCredentials(true) 不能同时使用
245
+ ```