Kaynağa Gözat

fix(S-cfc-154): admin.article.audit 权限流补全(B-142-1)使契约红单测转绿

- JwtInterceptor.LOGIN_REQUIRED_PATHS 追加 /api/admin/ 前缀:匿名无 token 访问 /api/admin/** 直接 401(/api/admin-auth/* 登录端点前缀不同且走 PUBLIC_PATHS,不受影响)
- AdminArticleController#audit 增加 @RequestAttribute("role") 角色守卫,非 admin 返回「无权限」且不触达 service(与 /move 守卫惯例一致)

契约:AdminArticleAuditContractTest 权限流-1/2/3 三红 → 全绿;正常流/边界流/service 状态机 9 例行为锁定不受影响。
Sisyphus 22 saat önce
ebeveyn
işleme
a79b26640

+ 6 - 1
cfc-backend/src/main/java/com/etotem/cfc/config/JwtInterceptor.java

@@ -139,7 +139,12 @@ private static final String[] PUBLIC_PATHS = {
         "/api/user/deactivate",             // 账号注销:隐私敏感
         // SC-X-22 CF 值获取预估:预估接口必须登录,游客无 token 直接 401,
         // 不泄露规则数值(契约 §7 第 1 行:不展示预估或「登录后可见」)。
-        "/api/reward/estimate"
+        "/api/reward/estimate",
+        // B-142-1(P1 安全):/api/admin/** 整族鉴权门缺失——匿名(userId=-1, role=anonymous)此前被
+        // 放行至 admin 业务 controller,可越权执行审核等敏感操作;现整族要求登录,无 token 直接 401。
+        // (/api/admin-auth/* 登录端点前缀不同且走 PUBLIC_PATHS 例外,不受影响;
+        //   契约:AdminArticleAuditContractTest 权限流-1/2,能力键 admin.article.audit / S-cfc-154)
+        "/api/admin/"
     };
 
     @Override

+ 6 - 1
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminArticleController.java

@@ -323,7 +323,12 @@ public class AdminArticleController {
 
     @PostMapping("/audit")
     public Result<String> audit(@RequestBody Map<String, Object> body,
-                                 @RequestAttribute("userId") Long adminId) {
+                                 @RequestAttribute("userId") Long adminId,
+                                 @RequestAttribute("role") String role) {
+        // B-142-1 角色守卫:仅平台 admin 可审核文章,与 /move 守卫惯例一致
+        if (!"admin".equals(role)) {
+            return Result.error("无权限");
+        }
         Long articleId = ParamUtils.getLong(body.get("id"));
         String auditStatus = (String) body.get("auditStatus");
         String auditReason = (String) body.get("auditReason");