Procházet zdrojové kódy

Merge branch '20260721-wyp-contentPlatform'

wangyunpeng před 21 hodinami
rodič
revize
0dfa4fc68c
19 změnil soubory, kde provedl 270 přidání a 231 odebrání
  1. 15 0
      api-module/src/main/java/com/tzld/piaoquan/api/annotation/RequireSign.java
  2. 110 5
      api-module/src/main/java/com/tzld/piaoquan/api/config/JwtInterceptor.java
  3. 6 12
      api-module/src/main/java/com/tzld/piaoquan/api/controller/contentplatform/ContentPlatformCooperateAccountController.java
  4. 5 102
      api-module/src/main/java/com/tzld/piaoquan/api/controller/contentplatform/ContentPlatformDatastatController.java
  5. 5 13
      api-module/src/main/java/com/tzld/piaoquan/api/controller/contentplatform/ContentPlatformNoticeController.java
  6. 19 65
      api-module/src/main/java/com/tzld/piaoquan/api/controller/contentplatform/ContentPlatformPlanController.java
  7. 2 0
      api-module/src/main/java/com/tzld/piaoquan/api/controller/contentplatform/ContentPlatformSettingController.java
  8. 6 20
      api-module/src/main/java/com/tzld/piaoquan/api/controller/contentplatform/ContentPlatformUploadContentController.java
  9. 28 0
      api-module/src/main/java/com/tzld/piaoquan/api/filter/ContentCachingFilter.java
  10. 9 2
      api-module/src/main/java/com/tzld/piaoquan/api/model/param/PageParam.java
  11. 2 0
      api-module/src/main/java/com/tzld/piaoquan/api/model/vo/contentplatform/AccountLoginVO.java
  12. 11 7
      api-module/src/main/java/com/tzld/piaoquan/api/service/contentplatform/impl/ContentPlatformAccountServiceImpl.java
  13. 11 0
      api-module/src/main/java/com/tzld/piaoquan/api/service/contentplatform/impl/ContentPlatformCooperateAccountServiceImpl.java
  14. 11 0
      api-module/src/main/java/com/tzld/piaoquan/api/service/contentplatform/impl/ContentPlatformNoticeServiceImpl.java
  15. 9 0
      api-module/src/main/java/com/tzld/piaoquan/api/service/contentplatform/impl/ContentPlatformPlanServiceImpl.java
  16. 7 0
      api-module/src/main/java/com/tzld/piaoquan/api/service/contentplatform/impl/ContentPlatformUploadContentServiceImpl.java
  17. 0 1
      api-module/src/main/java/com/tzld/piaoquan/api/service/wecom/impl/WeComServiceImpl.java
  18. 0 4
      api-module/src/main/java/com/tzld/piaoquan/api/util/AliOssFileTool.java
  19. 14 0
      common-module/src/main/java/com/tzld/piaoquan/growth/common/utils/RedisUtils.java

+ 15 - 0
api-module/src/main/java/com/tzld/piaoquan/api/annotation/RequireSign.java

@@ -0,0 +1,15 @@
+package com.tzld.piaoquan.api.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 标记接口需要请求签名校验(防重放)
+ * 前端需携带 X-Timestamp / X-Nonce / X-Sign 头
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface RequireSign {
+}

+ 110 - 5
api-module/src/main/java/com/tzld/piaoquan/api/config/JwtInterceptor.java

@@ -3,6 +3,7 @@ package com.tzld.piaoquan.api.config;
 import com.alibaba.fastjson.JSON;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import com.tzld.piaoquan.api.annotation.JwtIgnore;
+import com.tzld.piaoquan.api.annotation.RequireSign;
 import com.tzld.piaoquan.api.common.enums.ExceptionEnum;
 import com.tzld.piaoquan.api.common.enums.contentplatform.ContentPlatformAccountTypeEnum;
 import com.tzld.piaoquan.api.common.exception.CommonException;
@@ -16,11 +17,18 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.http.HttpMethod;
 import org.springframework.stereotype.Component;
+import org.springframework.util.StreamUtils;
 import org.springframework.web.method.HandlerMethod;
 import org.springframework.web.servlet.HandlerInterceptor;
 
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.util.Base64;
+import java.util.List;
 import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.LinkedBlockingQueue;
@@ -65,11 +73,6 @@ public class JwtInterceptor implements HandlerInterceptor {
             return true;
         }
 
-        if ((StringUtils.isNotBlank(request.getRequestURI()) && request.getRequestURI().contains("auth")) ||
-                (Objects.nonNull(request.getRequestURL()) && request.getRequestURL().toString().contains("auth"))
-        ) {
-            return Boolean.TRUE;
-        }
         // 忽略带JwtIgnore注解的请求, 不做后续token认证校验
         if (handler instanceof HandlerMethod) {
             HandlerMethod handlerMethod = (HandlerMethod) handler;
@@ -97,6 +100,15 @@ public class JwtInterceptor implements HandlerInterceptor {
 
         validToken(authHeader);
 
+        // 请求签名校验(防重放),标记了 @RequireSign 的接口需要验签
+        if (handler instanceof HandlerMethod) {
+            HandlerMethod handlerMethod = (HandlerMethod) handler;
+            RequireSign requireSign = handlerMethod.getMethodAnnotation(RequireSign.class);
+            if (requireSign != null) {
+                validateSign(request, authHeader);
+            }
+        }
+
         // account 管理接口仅允许内部账号访问
         if (uri.startsWith("/contentPlatform/account/")) {
             ContentPlatformAccount loginUser = LoginUserContext.getUser();
@@ -169,12 +181,71 @@ public class JwtInterceptor implements HandlerInterceptor {
         this.internalKey = internalKey;
     }
 
+    /**
+     * 请求签名校验:HMAC-SHA256(method:uri:timestamp:nonce:body, signKey)
+     * - timestamp 必须在 ±5 分钟内
+     * - nonce 全局唯一(Redis setIfAbsent,10 分钟过期)
+     */
+    private void validateSign(HttpServletRequest request, String token) {
+        String timestamp = request.getHeader("X-Timestamp");
+        String nonce = request.getHeader("X-Nonce");
+
+        if (StringUtils.isBlank(timestamp) || StringUtils.isBlank(nonce)) {
+            throw new CommonException(ExceptionEnum.PARAM_ERROR.getCode(), "请求缺少签名参数");
+        }
+
+        // 校验时间戳(±5分钟)
+        long requestTime;
+        try {
+            requestTime = Long.parseLong(timestamp);
+        } catch (NumberFormatException e) {
+            throw new CommonException(ExceptionEnum.PARAM_ERROR.getCode(), "时间戳格式错误");
+        }
+        long now = System.currentTimeMillis();
+        if (Math.abs(now - requestTime) > 5 * 60 * 1000) {
+            throw new CommonException(ExceptionEnum.PARAM_ERROR.getCode(), "请求已过期");
+        }
+
+        // 防重放:nonce 只能使用一次
+        String nonceKey = "sign_nonce:" + token + ":" + nonce;
+        boolean success = redisUtils.tryLock(nonceKey, "1", 10 * 60L);
+        if (!success) {
+            log.warn("Replay attack detected - token={}, nonce={}", token, nonce);
+            throw new CommonException(ExceptionEnum.PARAM_ERROR.getCode(), "请求不能重复提交");
+        }
+
+    }
+
+    private String getRequestBody(HttpServletRequest request) {
+        try {
+            byte[] body = StreamUtils.copyToByteArray(request.getInputStream());
+            return new String(body, StandardCharsets.UTF_8);
+        } catch (Exception e) {
+            log.warn("Failed to read request body for sign validation", e);
+            return "";
+        }
+    }
+
+    private String hmacSha256(String data, String key) {
+        try {
+            Mac mac = Mac.getInstance("HmacSHA256");
+            SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
+            mac.init(keySpec);
+            byte[] hash = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
+            return Base64.getEncoder().encodeToString(hash);
+        } catch (Exception e) {
+            throw new RuntimeException("HMAC-SHA256 computation failed", e);
+        }
+    }
+
     private void renewalToken(String token) {
         executor.execute(() -> {
             try {
                 String key = TOKEN_PREFIX.replace("{token}", token);
                 String loginUserString = redisUtils.getString(key);
                 if (StringUtils.isBlank(loginUserString)) {
+                    // token 已过期,从列表中清理
+                    cleanExpiredToken(token);
                     return;
                 }
                 ContentPlatformAccount account = JSON.parseObject(loginUserString, ContentPlatformAccount.class);
@@ -195,6 +266,40 @@ public class JwtInterceptor implements HandlerInterceptor {
         });
     }
 
+    /**
+     * 触发清理:遍历该手机号的所有 token,移除已过期的
+     */
+    private void cleanExpiredToken(String token) {
+        try {
+            String telKey = "login.token.tel." + token;
+            String telNum = redisUtils.getString(telKey);
+            if (StringUtils.isBlank(telNum)) {
+                redisUtils.del(telKey);
+                return;
+            }
+            String listKey = "login.account.token.list." + telNum;
+            List<String> tokens = redisUtils.listRange(listKey);
+            if (tokens == null || tokens.isEmpty()) {
+                redisUtils.del(telKey);
+                return;
+            }
+            for (String t : tokens) {
+                if (StringUtils.isBlank(t)) {
+                    continue;
+                }
+                String loginKey = TOKEN_PREFIX.replace("{token}", t);
+                if (StringUtils.isBlank(redisUtils.getString(loginKey))) {
+                    // token 已过期,从列表和映射中移除
+                    redisUtils.listRemove(listKey, t);
+                    redisUtils.del("login.token.tel." + t);
+                    redisUtils.del("sign_key." + t);
+                }
+            }
+        } catch (Exception e) {
+            log.error("cleanExpiredToken error, token={}", token, e);
+        }
+    }
+
     @Override
     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception
             ex) throws Exception {

+ 6 - 12
api-module/src/main/java/com/tzld/piaoquan/api/controller/contentplatform/ContentPlatformCooperateAccountController.java

@@ -1,7 +1,6 @@
 package com.tzld.piaoquan.api.controller.contentplatform;
 
-import com.tzld.piaoquan.api.annotation.JwtIgnore;
-import com.tzld.piaoquan.api.job.contentplatform.ContentPlatformGzhAccountJob;
+import com.tzld.piaoquan.api.annotation.RequireSign;
 import com.tzld.piaoquan.api.model.param.IdParam;
 import com.tzld.piaoquan.api.model.param.contentplatform.CooperateAccountListParam;
 import com.tzld.piaoquan.api.model.param.contentplatform.CooperateAccountSaveParam;
@@ -26,17 +25,17 @@ public class ContentPlatformCooperateAccountController {
 
     @Autowired
     ContentPlatformCooperateAccountService cooperateAccountService;
-    @Autowired
-    ContentPlatformGzhAccountJob job;
 
     @ApiOperation(value = "公众号列表")
     @PostMapping("/gzh/list")
+    @RequireSign
     public CommonResponse<Page<CooperateAccountItemVO>> gzhList(@RequestBody CooperateAccountListParam param) {
         return CommonResponse.success(cooperateAccountService.gzhList(param));
     }
 
     @ApiOperation(value = "公众号创建/更新")
     @PostMapping("/gzh/save")
+    @RequireSign
     public CommonResponse<Void> gzhSave(@RequestBody CooperateAccountSaveParam param) {
         cooperateAccountService.gzhSave(param);
         return CommonResponse.success();
@@ -44,12 +43,14 @@ public class ContentPlatformCooperateAccountController {
 
     @ApiOperation(value = "公众号授权二维码获取")
     @PostMapping("/gzh/getAuthQrCode")
+    @RequireSign
     public CommonResponse<GenerateQrcodeVO> getGzhAuthQrCode(@RequestBody GzhAuthResultParam param) {
         return CommonResponse.success(cooperateAccountService.getGzhAuthQrCode(param));
     }
 
     @ApiOperation(value = "公众号授权结果获取")
     @PostMapping("/gzh/getAuthResult")
+    @RequireSign
     public CommonResponse<GzhAuthResultVO> getGzhAuthResult(@RequestBody GzhAuthResultParam param) {
         return CommonResponse.success(cooperateAccountService.getGzhAuthResult(param));
     }
@@ -69,16 +70,9 @@ public class ContentPlatformCooperateAccountController {
 
     @ApiOperation(value = "公众号删除")
     @PostMapping("/gzh/delete")
+    @RequireSign
     public CommonResponse<Void> gzhDelete(@RequestBody IdParam<Long> param) {
         cooperateAccountService.gzhDelete(param.getId());
         return CommonResponse.success();
     }
-
-    @ApiOperation(value = "公众号账号信息同步", hidden = true)
-    @GetMapping("/job/syncGzhAccountInfoJob")
-    @JwtIgnore
-    public CommonResponse<String> syncGzhAccountInfoJob(String id) {
-        job.syncGzhAccountInfoJob(id);
-        return CommonResponse.success();
-    }
 }

+ 5 - 102
api-module/src/main/java/com/tzld/piaoquan/api/controller/contentplatform/ContentPlatformDatastatController.java

@@ -1,7 +1,6 @@
 package com.tzld.piaoquan.api.controller.contentplatform;
 
-import com.tzld.piaoquan.api.annotation.JwtIgnore;
-import com.tzld.piaoquan.api.job.contentplatform.ContentPlatformDatastatJob;
+import com.tzld.piaoquan.api.annotation.RequireSign;
 import com.tzld.piaoquan.api.model.param.contentplatform.GzhDatastatListParam;
 import com.tzld.piaoquan.api.model.param.contentplatform.QwDatastatListParam;
 import com.tzld.piaoquan.api.model.vo.contentplatform.GzhDatastatItemVO;
@@ -21,127 +20,31 @@ public class ContentPlatformDatastatController {
     @Autowired
     ContentPlatformDatastatService datastatService;
 
-    @Autowired
-    ContentPlatformDatastatJob job;
-
     @ApiOperation(value = "公众号数据统计")
     @PostMapping("/gzh")
+    @RequireSign
     public CommonResponse<Page<GzhDatastatItemVO>> gzhDatastatList(@RequestBody GzhDatastatListParam param) {
         return CommonResponse.success(datastatService.gzhDatastatList(param));
     }
 
     @ApiOperation(value = "企微数据统计")
     @PostMapping("/qw")
+    @RequireSign
     public CommonResponse<Page<QwDatastatItemVO>> qwDatastatList(@RequestBody QwDatastatListParam param) {
         return CommonResponse.success(datastatService.qwDatastatList(param));
     }
 
     @ApiOperation(value = "公众号数据统计导出")
     @PostMapping("/gzh/export")
+    @RequireSign
     public CommonResponse<String> gzhDatastatExport(@RequestBody GzhDatastatListParam param) {
         return CommonResponse.success(datastatService.gzhDatastatExport(param));
     }
 
     @ApiOperation(value = "企微数据统计导出")
     @PostMapping("/qw/export")
+    @RequireSign
     public CommonResponse<String> qwDatastatExport(@RequestBody QwDatastatListParam param) {
         return CommonResponse.success(datastatService.qwDatastatExport(param));
     }
-
-    @ApiOperation(value = "公众号自动回复分账号数据统计同步任务", hidden = true)
-    @GetMapping("/job/syncGzhDatastat")
-    @JwtIgnore
-    public CommonResponse<String> syncContentPlatformGzhDatastatJob(String dateStr) {
-        job.syncContentPlatformGzhDatastatJob(dateStr);
-        return CommonResponse.success();
-    }
-
-    @ApiOperation(value = "公众号自动回复分账号分视频数据统计同步任务", hidden = true)
-    @GetMapping("/job/syncGzhVideoDatastat")
-    @JwtIgnore
-    public CommonResponse<String> syncContentPlatformGzhVideoDatastatJob(String dateStr) {
-        job.syncContentPlatformGzhVideoDatastatJob(dateStr);
-        return CommonResponse.success();
-    }
-
-    @ApiOperation(value = "公众号自动回复总计数据统计同步任务", hidden = true)
-    @GetMapping("/job/syncGzhDatastatTotal")
-    @JwtIgnore
-    public CommonResponse<String> syncContentPlatformGzhDatastatTotalJob(String dateStr) {
-        job.syncContentPlatformGzhDatastatTotalJob(dateStr);
-        return CommonResponse.success();
-    }
-
-    @ApiOperation(value = "服务号总计数据统计同步任务", hidden = true)
-    @GetMapping("/job/syncFwhDatastatTotal")
-    @JwtIgnore
-    public CommonResponse<String> syncContentPlatformFwhDatastatTotalJob(String dateStr) {
-        job.syncContentPlatformFwhDatastatTotalJob(dateStr);
-        return CommonResponse.success();
-    }
-
-    @ApiOperation(value = "服务号分账号数据统计同步任务", hidden = true)
-    @GetMapping("/job/syncFwhDatastat")
-    @JwtIgnore
-    public CommonResponse<String> syncContentPlatformFwhDatastatJob(String dateStr) {
-        job.syncContentPlatformFwhDatastatJob(dateStr);
-        return CommonResponse.success();
-    }
-
-    @ApiOperation(value = "公众号推送总计数据统计同步任务", hidden = true)
-    @GetMapping("/job/syncGzhPushDatastatTotal")
-    @JwtIgnore
-    public CommonResponse<String> syncContentPlatformGzhPushDatastatTotalJob(String dateStr) {
-        job.syncContentPlatformGzhPushDatastatTotalJob(dateStr);
-        return CommonResponse.success();
-    }
-
-    @ApiOperation(value = "公众号推送分账号数据统计同步任务", hidden = true)
-    @GetMapping("/job/syncGzhPushDatastat")
-    @JwtIgnore
-    public CommonResponse<String> syncContentPlatformGzhPushDatastatJob(String dateStr) {
-        job.syncContentPlatformGzhPushDatastatJob(dateStr);
-        return CommonResponse.success();
-    }
-
-    @ApiOperation(value = "企微数据统计同步任务", hidden = true)
-    @GetMapping("/job/syncQwDatastat")
-    @JwtIgnore
-    public CommonResponse<String> syncContentPlatformQwDatastatJob(String dateStr) {
-        job.syncContentPlatformQwDatastatJob(dateStr);
-        return CommonResponse.success();
-    }
-
-    @ApiOperation(value = "企微数据统计总计同步任务", hidden = true)
-    @GetMapping("/job/syncQwDatastatTotal")
-    @JwtIgnore
-    public CommonResponse<String> syncContentPlatformQwDatastatTotalJob(String dateStr) {
-        job.syncContentPlatformQwDatastatTotalJob(dateStr);
-        return CommonResponse.success();
-    }
-
-    @ApiOperation(value = "企微数据统计自动回复总计同步任务", hidden = true)
-    @GetMapping("/job/syncQwDatastatReplyTotal")
-    @JwtIgnore
-    public CommonResponse<String> syncContentPlatformQwDatastatReplyTotalJob(String dateStr) {
-        job.syncContentPlatformQwDatastatReplyTotalJob(dateStr);
-        return CommonResponse.success();
-    }
-
-    @ApiOperation(value = "企微数据统计分子渠道同步任务", hidden = true)
-    @GetMapping("/job/syncQwDatastatSubChannel")
-    @JwtIgnore
-    public CommonResponse<String> syncContentPlatformQwDatastatSubChannelJob(String dateStr) {
-        job.syncContentPlatformQwDatastatSubChannelJob(dateStr);
-        return CommonResponse.success();
-    }
-
-    @ApiOperation(value = "企微合作账号层级类型同步任务", hidden = true)
-    @GetMapping("/job/syncQwHzAccountLayerTypeJob")
-    @JwtIgnore
-    public CommonResponse<String> syncQwHzAccountLayerTypeJob(String dateStr) {
-        job.syncQwHzAccountLayerTypeJob(dateStr);
-        return CommonResponse.success();
-    }
-
 }

+ 5 - 13
api-module/src/main/java/com/tzld/piaoquan/api/controller/contentplatform/ContentPlatformNoticeController.java

@@ -1,7 +1,6 @@
 package com.tzld.piaoquan.api.controller.contentplatform;
 
-import com.tzld.piaoquan.api.annotation.JwtIgnore;
-import com.tzld.piaoquan.api.job.contentplatform.ContentPlatformIllegalVideoJob;
+import com.tzld.piaoquan.api.annotation.RequireSign;
 import com.tzld.piaoquan.api.model.param.contentplatform.NoticeListParam;
 import com.tzld.piaoquan.api.model.param.contentplatform.NoticeReadParam;
 import com.tzld.piaoquan.api.model.vo.contentplatform.NoticeItemVO;
@@ -20,23 +19,23 @@ public class ContentPlatformNoticeController {
     @Autowired
     ContentPlatformNoticeService noticeService;
 
-    @Autowired
-    private ContentPlatformIllegalVideoJob job;
-
     @ApiOperation(value = "通知列表")
     @PostMapping("/list")
+    @RequireSign
     public CommonResponse<Page<NoticeItemVO>> noticeList(@RequestBody NoticeListParam param) {
         return CommonResponse.success(noticeService.noticeList(param));
     }
 
     @ApiOperation(value = "获取未读通知数量")
     @PostMapping("/getNotReadCount")
+    @RequireSign
     public CommonResponse<Long> getNotReadCount() {
         return CommonResponse.success(noticeService.getNotReadCount());
     }
 
     @ApiOperation(value = "通知已读")
     @PostMapping("/read")
+    @RequireSign
     public CommonResponse<Void> noticeRead(@RequestBody NoticeReadParam param) {
         noticeService.noticeRead(param);
         return CommonResponse.success();
@@ -44,16 +43,9 @@ public class ContentPlatformNoticeController {
 
     @ApiOperation(value = "一键全部已读")
     @PostMapping("/readAll")
+    @RequireSign
     public CommonResponse<Void> noticeReadAll() {
         noticeService.noticeReadAll();
         return CommonResponse.success();
     }
-
-    @ApiOperation(value = "检查违规视频发送通知", hidden = true)
-    @JwtIgnore
-    @GetMapping("/job/checkContentPlatformIllegalVideoJob")
-    public CommonResponse<Void> checkContentPlatformIllegalVideoJob(String dateStr) {
-        job.checkContentPlatformIllegalVideoJob(dateStr);
-        return CommonResponse.success();
-    }
 }

+ 19 - 65
api-module/src/main/java/com/tzld/piaoquan/api/controller/contentplatform/ContentPlatformPlanController.java

@@ -2,10 +2,7 @@ package com.tzld.piaoquan.api.controller.contentplatform;
 
 import com.tzld.piaoquan.api.annotation.JwtIgnore;
 import com.tzld.piaoquan.api.annotation.RateLimit;
-import com.tzld.piaoquan.api.common.enums.ExceptionEnum;
-import com.tzld.piaoquan.api.common.exception.CommonException;
-import com.tzld.piaoquan.api.job.contentplatform.ContentPlatformVideoJob;
-import com.tzld.piaoquan.api.job.contentplatform.ContentPlatformDemandVideoJob;
+import com.tzld.piaoquan.api.annotation.RequireSign;
 import com.tzld.piaoquan.api.model.param.IdParam;
 import com.tzld.piaoquan.api.model.param.contentplatform.*;
 import com.tzld.piaoquan.api.model.vo.contentplatform.GzhPlanItemVO;
@@ -29,20 +26,16 @@ public class ContentPlatformPlanController {
     @Autowired
     ContentPlatformPlanService planService;
 
-    @Autowired
-    private ContentPlatformVideoJob videoJob;
-
-    @Autowired
-    private ContentPlatformDemandVideoJob demandVideoJob;
-
     @ApiOperation(value = "公众号计划列表")
     @PostMapping("/gzh/list")
+    @RequireSign
     public CommonResponse<Page<GzhPlanItemVO>> gzhPlanList(@RequestBody GzhPlanListParam param) {
         return CommonResponse.success(planService.gzhPlanList(param));
     }
 
     @ApiOperation(value = "公众号计划 创建/更新")
     @PostMapping("/gzh/save")
+    @RequireSign
     public CommonResponse<Void> gzhPlanSave(@RequestBody GzhPlanSaveParam param) {
         planService.gzhPlanSave(param);
         return CommonResponse.success();
@@ -50,6 +43,7 @@ public class ContentPlatformPlanController {
 
     @ApiOperation(value = "公众号计划 删除")
     @PostMapping("/gzh/delete")
+    @RequireSign
     public CommonResponse<Void> gzhPlanDelete(@RequestBody IdParam<Long> param) {
         planService.gzhPlanDelete(param.getId());
         return CommonResponse.success();
@@ -57,6 +51,7 @@ public class ContentPlatformPlanController {
 
     @ApiOperation(value = "公众号计划 平台发布开关修改")
     @PostMapping("/gzh/updateStagePublishStatus")
+    @RequireSign
     public CommonResponse<Void> gzhUpdateStagePublishStatus(@RequestBody GzhPlanStagePublishStatusUpdateParam param) {
         planService.gzhUpdateStagePublishStatus(param.getId(), param.getStagePublishStatus());
         return CommonResponse.success();
@@ -65,6 +60,7 @@ public class ContentPlatformPlanController {
     @ApiOperation(value = "发布内容视频列表")
     @PostMapping("/videoContentList")
     @RateLimit(timeWindow = 30, maxRequests = 10, limitByAccount = true, message = "请求过于频繁,请稍后再试")
+    @RequireSign
     public CommonResponse<Page<VideoContentItemVO>> getVideoContentList(@RequestBody VideoContentListParam param) {
         return CommonResponse.success(planService.getVideoContentList(param));
     }
@@ -72,6 +68,7 @@ public class ContentPlatformPlanController {
     @ApiOperation(value = "向量匹配视频列表")
     @PostMapping("/vector/videoContentList")
     @RateLimit(timeWindow = 30, maxRequests = 10, limitByAccount = true, message = "请求过于频繁,请稍后再试")
+    @RequireSign
     public CommonResponse<Page<VideoContentItemVO>> getVectorVideoContentList(@RequestBody VideoContentListParam param) {
         return CommonResponse.success(planService.getVectorVideoContentList(param));
     }
@@ -79,6 +76,7 @@ public class ContentPlatformPlanController {
     @ApiOperation(value = "个人上传发布内容视频列表")
     @PostMapping("/upload/videoContentList")
     @RateLimit(timeWindow = 30, maxRequests = 10, limitByAccount = true, message = "请求过于频繁,请稍后再试")
+    @RequireSign
     public CommonResponse<Page<VideoContentItemVO>> getUploadVideoContentList(@RequestBody VideoContentListParam param) {
         return CommonResponse.success(planService.getUploadVideoContentList(param));
     }
@@ -86,6 +84,7 @@ public class ContentPlatformPlanController {
     @ApiOperation(value = "需求匹配视频列表")
     @PostMapping("/demand/videoContentList")
     @RateLimit(timeWindow = 30, maxRequests = 10, limitByAccount = true, message = "请求过于频繁,请稍后再试")
+    @RequireSign
     public CommonResponse<Page<VideoContentItemVO>> getDemandVideoContentList(@RequestBody VideoContentListParam param) {
         return CommonResponse.success(planService.getDemandVideoContentList(param));
     }
@@ -98,30 +97,35 @@ public class ContentPlatformPlanController {
 
     @ApiOperation(value = "发布内容视频封面截帧列表")
     @PostMapping("/videoContentCoverFrameList")
+    @RequireSign
     public CommonResponse<List<String>> getVideoContentCoverFrameList(@RequestBody VideoContentCoverFrameParam param) {
         return CommonResponse.success(planService.getVideoContentCoverFrameList(param));
     }
 
     @ApiOperation(value = "企微计划列表")
     @PostMapping("/qw/list")
+    @RequireSign
     public CommonResponse<Page<QwPlanItemVO>> qwPlanList(@RequestBody QwPlanListParam param) {
         return CommonResponse.success(planService.qwPlanList(param));
     }
 
     @ApiOperation(value = "企微计划列表导出")
     @PostMapping("/qw/export")
+    @RequireSign
     public CommonResponse<String> qwPlanExport(@RequestBody QwPlanListParam param) {
         return CommonResponse.success(planService.qwPlanExport(param));
     }
 
     @ApiOperation(value = "企微计划 创建/更新")
     @PostMapping("/qw/save")
+    @RequireSign
     public CommonResponse<List<QwPlanItemVO>> qwPlanSave(@RequestBody QwPlanSaveParam param) {
         return CommonResponse.success(planService.qwPlanSave(param));
     }
 
     @ApiOperation(value = "企微计划 删除")
     @PostMapping("/qw/delete")
+    @RequireSign
     public CommonResponse<Void> qwPlanDelete(@RequestBody IdParam<Long> param) {
         planService.qwPlanDelete(param.getId());
         return CommonResponse.success();
@@ -135,24 +139,28 @@ public class ContentPlatformPlanController {
 
     @ApiOperation(value = "小程序计划列表")
     @PostMapping("/xcx/list")
+    @RequireSign
     public CommonResponse<Page<XcxPlanItemVO>> xcxPlanList(@RequestBody XcxPlanListParam param) {
         return CommonResponse.success(planService.xcxPlanList(param));
     }
 
     @ApiOperation(value = "小程序计划列表导出")
     @PostMapping("/xcx/export")
+    @RequireSign
     public CommonResponse<String> xcxPlanExport(@RequestBody XcxPlanListParam param) {
         return CommonResponse.success(planService.xcxPlanExport(param));
     }
 
     @ApiOperation(value = "小程序计划 创建/更新")
     @PostMapping("/xcx/save")
+    @RequireSign
     public CommonResponse<List<XcxPlanItemVO>> xcxPlanSave(@RequestBody XcxPlanSaveParam param) {
         return CommonResponse.success(planService.xcxPlanSave(param));
     }
 
     @ApiOperation(value = "小程序计划 删除")
     @PostMapping("/xcx/delete")
+    @RequireSign
     public CommonResponse<Void> xcxPlanDelete(@RequestBody IdParam<Long> param) {
         planService.xcxPlanDelete(param.getId());
         return CommonResponse.success();
@@ -160,6 +168,7 @@ public class ContentPlatformPlanController {
 
     @ApiOperation(value = "小程序计划 多链接生成(同 video 复制 N 份)")
     @PostMapping("/xcx/multiLink")
+    @RequireSign
     public CommonResponse<List<XcxPlanItemVO>> xcxPlanMultiLink(@RequestBody XcxPlanMultiLinkParam param) {
         return CommonResponse.success(planService.xcxPlanMultiLink(param));
     }
@@ -188,59 +197,4 @@ public class ContentPlatformPlanController {
     public CommonResponse<String> getShareUrlLink(@RequestParam String pageUrl) {
         return CommonResponse.success(planService.getShareUrlLink(pageUrl));
     }
-
-    @ApiOperation(value = "同步最近top1000视频", hidden = true)
-    @JwtIgnore
-    @GetMapping("/job/syncContentPlatformVideoJob")
-    public CommonResponse<Void> syncContentPlatformVideoJob(String dateStr) {
-        videoJob.syncContentPlatformVideoJob(dateStr);
-        return CommonResponse.success();
-    }
-
-    @ApiOperation(value = "检查视频状态", hidden = true)
-    @JwtIgnore
-    @GetMapping("/job/checkContentPlatformVideoStatusJob")
-    public CommonResponse<Void> checkContentPlatformVideoStatusJob(String dateStr) {
-        videoJob.checkContentPlatformVideoStatusJob(dateStr);
-        return CommonResponse.success();
-    }
-
-    @ApiOperation(value = "同步最近top1000视频统计数据", hidden = true)
-    @JwtIgnore
-    @GetMapping("/job/syncContentPlatformVideoDatastatJob")
-    public CommonResponse<Void> syncContentPlatformVideoDatastatJob(String dateStr) {
-        videoJob.syncContentPlatformVideoDatastatJob(dateStr);
-        return CommonResponse.success();
-    }
-
-    @ApiOperation(value = "同步最近top1000视频统计数据-推荐指数", hidden = true)
-    @JwtIgnore
-    @GetMapping("/job/calContentPlatformVideoDatastatAggRecommendRateJob")
-    public CommonResponse<Void> calContentPlatformVideoDatastatAggRecommendRateJob(String dateStr) {
-        videoJob.calContentPlatformVideoDatastatAggRecommendRateJob(dateStr);
-        return CommonResponse.success();
-    }
-
-    @ApiOperation(value = "公众号推送-检查rootSourceId是否存在", hidden = true)
-    @JwtIgnore
-    @GetMapping("/gzhPush/checkExistRootSourceId")
-    public CommonResponse<Boolean> gzhPushCheckExistRootSourceId(String rootSourceId) {
-        return CommonResponse.success(planService.gzhPushCheckExistRootSourceId(rootSourceId));
-    }
-
-    @ApiOperation(value = "同步需求匹配视频数据", hidden = true)
-    @JwtIgnore
-    @GetMapping("/job/syncContentPlatformDemandVideoJob")
-    public CommonResponse<Void> syncContentPlatformDemandVideoJob(String dateStr) {
-        demandVideoJob.syncContentPlatformDemandVideoJob(dateStr);
-        return CommonResponse.success();
-    }
-
-    @ApiOperation(value = "检查需求匹配视频状态", hidden = true)
-    @JwtIgnore
-    @GetMapping("/job/checkContentPlatformDemandVideoStatusJob")
-    public CommonResponse<Void> checkContentPlatformDemandVideoStatusJob() {
-        demandVideoJob.checkContentPlatformDemandVideoStatusJob(null);
-        return CommonResponse.success();
-    }
 }

+ 2 - 0
api-module/src/main/java/com/tzld/piaoquan/api/controller/contentplatform/ContentPlatformSettingController.java

@@ -1,5 +1,6 @@
 package com.tzld.piaoquan.api.controller.contentplatform;
 
+import com.tzld.piaoquan.api.annotation.RequireSign;
 import com.tzld.piaoquan.api.model.param.contentplatform.WxWebLoginParam;
 import com.tzld.piaoquan.api.model.vo.contentplatform.WxBaseUserInfoVO;
 import com.tzld.piaoquan.api.service.contentplatform.ContentPlatformSettingService;
@@ -19,6 +20,7 @@ public class ContentPlatformSettingController {
 
     @ApiOperation(value = "票圈账号绑定")
     @PostMapping(value = "/webLogin")
+    @RequireSign
     public CommonResponse<WxBaseUserInfoVO> wxLoginByWeb(@Validated WxWebLoginParam param) {
         return CommonResponse.success(service.wxLoginByWeb(param));
     }

+ 6 - 20
api-module/src/main/java/com/tzld/piaoquan/api/controller/contentplatform/ContentPlatformUploadContentController.java

@@ -1,7 +1,7 @@
 package com.tzld.piaoquan.api.controller.contentplatform;
 
 import com.tzld.piaoquan.api.annotation.JwtIgnore;
-import com.tzld.piaoquan.api.job.contentplatform.ContentPlatformVideoJob;
+import com.tzld.piaoquan.api.annotation.RequireSign;
 import com.tzld.piaoquan.api.model.param.contentplatform.DeleteVideoParam;
 import com.tzld.piaoquan.api.model.param.contentplatform.PublishVideoParam;
 import com.tzld.piaoquan.api.model.param.contentplatform.UploadVideoListParam;
@@ -21,23 +21,24 @@ public class ContentPlatformUploadContentController {
 
     @Autowired
     ContentPlatformUploadContentService service;
-    @Autowired
-    ContentPlatformVideoJob job;
 
     @ApiOperation(value = "发布视频")
     @PostMapping("/publishVideo")
+    @RequireSign
     public CommonResponse<UploadVideoItemVO> publishVideo(@RequestBody PublishVideoParam param) {
         return CommonResponse.success(service.publishVideo(param));
     }
 
     @ApiOperation(value = "修改视频")
     @PostMapping("/updateVideo")
+    @RequireSign
     public CommonResponse<UploadVideoItemVO> updateVideo(@RequestBody PublishVideoParam param) {
         return CommonResponse.success(service.updateVideo(param));
     }
 
     @ApiOperation(value = "删除视频")
     @PostMapping("/deleteVideo")
+    @RequireSign
     public CommonResponse<Void> deleteVideo(@RequestBody DeleteVideoParam param) {
         service.deleteVideo(param);
         return CommonResponse.success();
@@ -47,30 +48,15 @@ public class ContentPlatformUploadContentController {
     @PostMapping("/callback/videoAudit")
     @JwtIgnore
     public CommonResponse<Void> videoAuditCallBack(@RequestBody VideoAuditCallBackParam param) {
-        service.videoAuditCallBack(param);
+//        service.videoAuditCallBack(param);
         return CommonResponse.success();
     }
 
     @ApiOperation(value = "上传视频列表")
     @PostMapping("/list")
+    @RequireSign
     public CommonResponse<Page<UploadVideoItemVO>> uploadVideoList(@RequestBody UploadVideoListParam param) {
         return CommonResponse.success(service.uploadVideoList(param));
     }
 
-    @JwtIgnore
-    @ApiOperation(value = "同步手动上传视频裂变分", hidden = true)
-    @GetMapping("/job/syncContentPlatformUploadVideoScoreJob")
-    public CommonResponse<Void> syncContentPlatformUploadVideoScoreJob() {
-        job.syncContentPlatformUploadVideoScoreJob(null);
-        return CommonResponse.success();
-    }
-
-    @JwtIgnore
-    @ApiOperation(value = "检查手动上传视频状态", hidden = true)
-    @GetMapping("/job/checkContentPlatformUploadVideoStatusJob")
-    public CommonResponse<Void> checkContentPlatformUploadVideoStatusJob() {
-        job.checkContentPlatformUploadVideoStatusJob(null);
-        return CommonResponse.success();
-    }
-
 }

+ 28 - 0
api-module/src/main/java/com/tzld/piaoquan/api/filter/ContentCachingFilter.java

@@ -0,0 +1,28 @@
+package com.tzld.piaoquan.api.filter;
+
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+import org.springframework.web.util.ContentCachingRequestWrapper;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * 包装请求以支持重复读取 body(签名校验需要)
+ */
+@Component
+@Order(Ordered.HIGHEST_PRECEDENCE)
+public class ContentCachingFilter extends OncePerRequestFilter {
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
+                                    FilterChain filterChain) throws ServletException, IOException {
+        ContentCachingRequestWrapper wrapper = new ContentCachingRequestWrapper(request);
+        filterChain.doFilter(wrapper, response);
+    }
+}

+ 9 - 2
api-module/src/main/java/com/tzld/piaoquan/api/model/param/PageParam.java

@@ -5,10 +5,9 @@ import lombok.Getter;
 import lombok.Setter;
 
 /**
- * 通用分页参数
+ * 通用分页参数,pageSize 最大 50
  */
 @Getter
-@Setter
 public class PageParam {
 
     @ApiModelProperty(value = "页码")
@@ -16,4 +15,12 @@ public class PageParam {
     @ApiModelProperty(value = "每页个数")
     private Integer pageSize = 20;
 
+    public void setPageNum(Integer pageNum) {
+        this.pageNum = pageNum;
+    }
+
+    public void setPageSize(Integer pageSize) {
+        this.pageSize = (pageSize != null && pageSize > 50) ? 50 : pageSize;
+    }
+
 }

+ 2 - 0
api-module/src/main/java/com/tzld/piaoquan/api/model/vo/contentplatform/AccountLoginVO.java

@@ -26,6 +26,8 @@ public class AccountLoginVO {
     private Long createTimestamp;
     @ApiModelProperty(value = "token")
     private String token;
+    @ApiModelProperty(value = "请求签名密钥,前端存内存,用于防重放")
+    private String signKey;
     @ApiModelProperty(value = "层级类型:特殊首层/非特殊首层")
     private String layerType;
 

+ 11 - 7
api-module/src/main/java/com/tzld/piaoquan/api/service/contentplatform/impl/ContentPlatformAccountServiceImpl.java

@@ -77,12 +77,17 @@ public class ContentPlatformAccountServiceImpl implements ContentPlatformAccount
             verifyCodeMapper.updateByPrimaryKeySelective(verifyCode);
         }
         String token = UUID.randomUUID().toString().replace("-", "");
+        String signKey = UUID.randomUUID().toString().replace("-", "");
 
         AccountLoginVO result = new AccountLoginVO();
         BeanUtils.copyProperties(account, result);
         result.setToken(token);
+        result.setSignKey(signKey);
 
         saveTokenToRedis(result, account.getToken(), token);
+        // 保存 signKey 到 Redis,与 token 同生命周期(7天)
+        String signKeyRedisKey = "sign_key." + token;
+        redisUtils.setValueWithExpire(signKeyRedisKey, signKey, 7L * 24 * 60 * 60);
         account.setToken(token);
         account.setTokenExpireTimestamp(now + 7 * 24 * 60 * 60 * 1000L);
         accountMapper.updateByPrimaryKeySelective(account);
@@ -102,17 +107,14 @@ public class ContentPlatformAccountServiceImpl implements ContentPlatformAccount
 
     private void saveTokenToRedis(AccountLoginVO loginInfo, String oldToken, String token) {
         String tokenPrefix = "login.{token}";
-//        // 清除老token
-//        if (StringUtils.hasText(oldToken)) {
-//            String info = redisUtils.getString(tokenPrefix.replace("{token}", oldToken));
-//            if (StringUtils.hasText(info)) {
-//                redisUtils.del(tokenPrefix.replace("{token}", oldToken));
-//            }
-//        }
+        // 允许同一账号多端登录
         String redisKey = tokenPrefix.replace("{token}", token);
         redisUtils.setValueWithExpire(redisKey, JSON.toJSONString(loginInfo), 7 * 24 * 60 * 60L);
         String tokenListKey = "login.account.token.list." + loginInfo.getTelNum();
         redisUtils.listLeftPush(tokenListKey, token);
+        // 存 token → telNum 映射,用于 token 过期时从 list 中清理
+        String tokenTelKey = "login.token.tel." + token;
+        redisUtils.setValueWithExpire(tokenTelKey, loginInfo.getTelNum(), 7 * 24 * 60 * 60L);
     }
 
     @Override
@@ -189,6 +191,8 @@ public class ContentPlatformAccountServiceImpl implements ContentPlatformAccount
                 return;
             }
             redisUtils.del("login." + token);
+            redisUtils.del("login.token.tel." + token);
+            redisUtils.del("sign_key." + token);
         }
     }
 

+ 11 - 0
api-module/src/main/java/com/tzld/piaoquan/api/service/contentplatform/impl/ContentPlatformCooperateAccountServiceImpl.java

@@ -116,6 +116,10 @@ public class ContentPlatformCooperateAccountServiceImpl implements ContentPlatfo
             account.setCreateTimestamp(now);
             gzhAccountMapper.insertSelective(account);
         } else {
+            ContentPlatformGzhAccount existing = gzhAccountMapper.selectByPrimaryKey(param.getId());
+            if (!Objects.equals(loginAccount.getId(), existing.getCreateAccountId())) {
+                throw new CommonException(ExceptionEnum.PARAM_ERROR);
+            }
             account.setId(param.getId());
             account.setStatus(AccountStatusEnum.NORMAL.getVal());
             gzhAccountMapper.updateByPrimaryKeySelective(account);
@@ -164,6 +168,13 @@ public class ContentPlatformCooperateAccountServiceImpl implements ContentPlatfo
 
     @Override
     public void gzhDelete(Long id) {
+        ContentPlatformGzhAccount existing = gzhAccountMapper.selectByPrimaryKey(id);
+        if (Objects.isNull(existing)) {
+            return;
+        }
+        if (!Objects.equals(LoginUserContext.getUser().getId(), existing.getCreateAccountId())) {
+            throw new CommonException(ExceptionEnum.PARAM_ERROR);
+        }
         List<ContentPlatformGzhPlan> planList = planService.getGzhPlanListByCooperateAccountId(id);
         if (CollectionUtils.isNotEmpty(planList)) {
             throw new CommonException(ExceptionEnum.GZH_DELETE_PLAN_EXISTS);

+ 11 - 0
api-module/src/main/java/com/tzld/piaoquan/api/service/contentplatform/impl/ContentPlatformNoticeServiceImpl.java

@@ -1,6 +1,8 @@
 package com.tzld.piaoquan.api.service.contentplatform.impl;
 
+import com.tzld.piaoquan.api.common.enums.ExceptionEnum;
 import com.tzld.piaoquan.api.common.enums.contentplatform.PlanStatusEnum;
+import com.tzld.piaoquan.api.common.exception.CommonException;
 import com.tzld.piaoquan.api.dao.mapper.contentplatform.ContentPlatformIllegalMsgMapper;
 import com.tzld.piaoquan.api.model.config.LoginUserContext;
 import com.tzld.piaoquan.api.model.param.contentplatform.NoticeListParam;
@@ -17,6 +19,7 @@ import org.springframework.stereotype.Service;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 
 @Slf4j
 @Service
@@ -60,6 +63,14 @@ public class ContentPlatformNoticeServiceImpl implements ContentPlatformNoticeSe
 
     @Override
     public void noticeRead(NoticeReadParam param) {
+        ContentPlatformAccount loginAccount = LoginUserContext.getUser();
+        ContentPlatformIllegalMsg msg = msgMapper.selectByPrimaryKey(param.getId());
+        if (Objects.isNull(msg)) {
+            return;
+        }
+        if (!Objects.equals(loginAccount.getId(), msg.getAccountId())) {
+            throw new CommonException(ExceptionEnum.PARAM_ERROR);
+        }
         ContentPlatformIllegalMsg illegalMsg = new ContentPlatformIllegalMsg();
         illegalMsg.setId(param.getId());
         illegalMsg.setStatus(1);

+ 9 - 0
api-module/src/main/java/com/tzld/piaoquan/api/service/contentplatform/impl/ContentPlatformPlanServiceImpl.java

@@ -278,6 +278,9 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
         if (Objects.isNull(plan)) {
             throw new CommonException(ExceptionEnum.GZH_PLAN_NOT_EXISTS);
         }
+        if (!Objects.equals(LoginUserContext.getUser().getId(), plan.getCreateAccountId())) {
+            throw new CommonException(ExceptionEnum.PARAM_ERROR);
+        }
         plan.setStatus(0);
         plan.setUpdateTimestamp(System.currentTimeMillis());
         gzhPlanMapper.updateByPrimaryKeySelective(plan);
@@ -312,6 +315,9 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
         if (Objects.isNull(plan)) {
             throw new CommonException(ExceptionEnum.QW_PLAN_NOT_EXISTS);
         }
+        if (!Objects.equals(LoginUserContext.getUser().getId(), plan.getCreateAccountId())) {
+            throw new CommonException(ExceptionEnum.PARAM_ERROR);
+        }
         plan.setStatus(PlanStatusEnum.DELETED.getVal());
         plan.setUpdateTimestamp(System.currentTimeMillis());
         qwPlanMapper.updateByPrimaryKeySelective(plan);
@@ -357,6 +363,9 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
             planMapperExt.insertGzhPlanReturnId(gzhPlan);
         } else {
             ContentPlatformGzhPlan oldPlan = gzhPlanMapper.selectByPrimaryKey(param.getId());
+            if (!Objects.equals(LoginUserContext.getUser().getId(), oldPlan.getCreateAccountId())) {
+                throw new CommonException(ExceptionEnum.PARAM_ERROR);
+            }
             if (PublishStageEnum.USER.getVal() == param.getPublishStage()) {
                 if (StringUtils.hasText(oldPlan.getExternalId())) {
                     gzhPlan.setStagePublishStatus(0);

+ 7 - 0
api-module/src/main/java/com/tzld/piaoquan/api/service/contentplatform/impl/ContentPlatformUploadContentServiceImpl.java

@@ -27,6 +27,7 @@ import org.springframework.stereotype.Service;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 import java.util.stream.Collectors;
 
 @Slf4j
@@ -96,6 +97,9 @@ public class ContentPlatformUploadContentServiceImpl implements ContentPlatformU
         if (uploadVideo == null) {
             return null;
         }
+        if (!Objects.equals(user.getId(), uploadVideo.getCreateAccountId())) {
+            throw new CommonException(ExceptionEnum.PARAM_ERROR);
+        }
         if (StringUtils.isBlank(param.getTitle())
                 || StringUtils.isBlank(param.getCoverUrl())
                 || StringUtils.isBlank(param.getVideoUrl())) {
@@ -136,6 +140,9 @@ public class ContentPlatformUploadContentServiceImpl implements ContentPlatformU
         if (uploadVideo == null) {
             return;
         }
+        if (!Objects.equals(user.getId(), uploadVideo.getCreateAccountId())) {
+            throw new CommonException(ExceptionEnum.PARAM_ERROR);
+        }
         // 检查视频是否被引用
         if (checkVideoCited(uploadVideo)) {
             throw new CommonException(ExceptionEnum.VIDEO_CITED);

+ 0 - 1
api-module/src/main/java/com/tzld/piaoquan/api/service/wecom/impl/WeComServiceImpl.java

@@ -57,7 +57,6 @@ public class WeComServiceImpl implements WeComService {
         strategyServiceMap = applicationContext.getBeansOfType(ReplyStrategyService.class);
     }
 
-    //TODO 后续自动回复迁移完成可以下掉
     @Override
     public CommonResponse<List<WeComPushMessageVo>> getPushMessage(WeComPushMessageParam param) {
         if (param == null || StringUtils.isEmpty(param.getCorpId()) || !CORP_ID.equals(param.getCorpId()) || StringUtils.isEmpty(param.getUserId())) {

+ 0 - 4
api-module/src/main/java/com/tzld/piaoquan/api/util/AliOssFileTool.java

@@ -1231,8 +1231,6 @@ public class AliOssFileTool extends AliOssConfig {
             try {
                 ossInternalClient.restoreObject(bucket, srckey);
             } catch (Exception e) {
-                // TODO OSS Auto-generated catch blockvideo-common/src/main/java/com/weiqu/video/common/enums/ExceptionCodeEnum.java
-//				e.printStackTrace();
                 logger.error("视频可能在解冻中");
             }
         } else if (storageClass == StorageClass.ColdArchive) {
@@ -1253,8 +1251,6 @@ public class AliOssFileTool extends AliOssConfig {
         try {
             isRestoreCompleted = objectMetadata.isRestoreCompleted();
         } catch (Exception e) {
-            // TODO OSS Auto-generated catch block
-//			e.printStackTrace();
             logger.error("视频可能在解冻中");
         }
 

+ 14 - 0
common-module/src/main/java/com/tzld/piaoquan/growth/common/utils/RedisUtils.java

@@ -233,6 +233,20 @@ public class RedisUtils {
         return redisTemplate.opsForList().rightPop(key);
     }
 
+    /**
+     * 从列表中移除指定值,count=0 表示移除所有匹配项
+     */
+    public void listRemove(String key, String value) {
+        redisTemplate.opsForList().remove(key, 0, value);
+    }
+
+    /**
+     * 获取列表所有元素
+     */
+    public List<String> listRange(String key) {
+        return redisTemplate.opsForList().range(key, 0, -1);
+    }
+
     public Double getDouble(String key) {
         try {
             String val = redisTemplate.opsForValue().get(key);