Pārlūkot izejas kodu

refactor(core): 优化系统核心配置及安全过滤逻辑

- 移除 AdvertisingForm 和 BannerInfoForm 中的主键非空校验注解
- 在 AdvertisingMapper.xml 和 BannerInfoMapper.xml 查询中增加 is_deleted = 0 过滤条件并按 sort 倒序排列
- 完善 AliyunFileService 的初始化、上传与删除功能,加入日志记录和异常处理机制
- 将 application.yml 激活环境由 prod 改为 dev,并调整开发环境配置文件中的请求头检查项
- 修改生产环境 OSS 配置为阿里云,并更新对应的 accessKeyId、secret 和 bucketName
- 调整 UserFeedback 实体类字段命名:describe → desc,filesUrl → images
- 更新 MyMetaObjectHandler 自动填充逻辑,新增创建人和更新人字段注入
- 在 XssAndSqlInjectionFilter 中移除对 Cookie 请求头的安全检查
- 日志配置文件中添加默认 root logger 输出控制台和文件的配置段落
wzq 5 dienas atpakaļ
vecāks
revīzija
19e3593890

+ 2 - 2
src/main/java/com/zsElectric/boot/business/model/entity/UserFeedback.java

@@ -30,11 +30,11 @@ public class UserFeedback extends BaseEntity {
     /**
      * 问题描述
      */
-    private String describe;
+    private String desc;
     /**
      * 相关图片地址
      */
-    private String filesUrl;
+    private String images;
     /**
      * 联系方式(手机号或者邮箱)
      */

+ 0 - 1
src/main/java/com/zsElectric/boot/business/model/form/AdvertisingForm.java

@@ -24,7 +24,6 @@ public class AdvertisingForm implements Serializable {
     private static final long serialVersionUID = 1L;
 
     @Schema(description = "主键")
-    @NotNull(message = "主键不能为空")
     private Long id;
 
     @Schema(description = "标题")

+ 0 - 1
src/main/java/com/zsElectric/boot/business/model/form/BannerInfoForm.java

@@ -24,7 +24,6 @@ public class BannerInfoForm implements Serializable {
     private static final long serialVersionUID = 1L;
 
     @Schema(description = "主键")
-    @NotNull(message = "主键不能为空")
     private Long id;
 
     @Schema(description = "banner图片")

+ 2 - 3
src/main/java/com/zsElectric/boot/business/model/form/UserFeedbackForm.java

@@ -24,7 +24,6 @@ public class UserFeedbackForm implements Serializable {
     private static final long serialVersionUID = 1L;
 
     @Schema(description = "主键")
-    @NotNull(message = "主键不能为空")
     private Long id;
 
     @Schema(description = "问题类型(1投诉吐槽,2功能异常,3体验问题,4功能建议,9其他 )")
@@ -33,11 +32,11 @@ public class UserFeedbackForm implements Serializable {
 
     @Schema(description = "问题描述")
     @Size(max=500, message="问题描述长度不能超过500个字符")
-    private String describe;
+    private String desc;
 
     @Schema(description = "相关图片地址")
     @Size(max=600, message="相关图片地址长度不能超过600个字符")
-    private String filesUrl;
+    private String images;
 
     @Schema(description = "联系方式(手机号或者邮箱)")
     @Size(max=255, message="联系方式(手机号或者邮箱)长度不能超过255个字符")

+ 1 - 1
src/main/java/com/zsElectric/boot/business/model/vo/BannerInfoVO.java

@@ -32,7 +32,7 @@ public class BannerInfoVO implements Serializable {
     private String jumpAppid;
     @Schema(description = "跳转页面")
     private String jumpPage;
-    @Schema(description = "排序 越大越靠前")
+    @Schema(description = "排序")
     private Integer sort;
     @Schema(description = "状态 0-禁用 1-启用")
     private Integer status;

+ 2 - 2
src/main/java/com/zsElectric/boot/business/model/vo/UserFeedbackVO.java

@@ -27,9 +27,9 @@ public class UserFeedbackVO implements Serializable {
     @Schema(description = "问题类型(1投诉吐槽,2功能异常,3体验问题,4功能建议,9其他 )")
     private Integer type;
     @Schema(description = "问题描述")
-    private String describe;
+    private String desc;
     @Schema(description = "相关图片地址")
-    private String filesUrl;
+    private String images;
     @Schema(description = "联系方式(手机号或者邮箱)")
     private String contactWay;
     @Schema(description = "答复信息")

+ 0 - 1
src/main/java/com/zsElectric/boot/core/filter/XssAndSqlInjectionFilter.java

@@ -52,7 +52,6 @@ public class XssAndSqlInjectionFilter implements Filter {
      * 默认需要检查的请求头
      */
     private static final Set<String> DEFAULT_CHECK_HEADERS = new HashSet<>(Arrays.asList(
-            "Cookie",
             "Referer",
             "X-Forwarded-For"
     ));

+ 27 - 8
src/main/java/com/zsElectric/boot/platform/file/service/impl/AliyunFileService.java

@@ -5,6 +5,7 @@ import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.lang.Assert;
 import cn.hutool.core.util.IdUtil;
 import com.aliyun.oss.OSS;
+import com.aliyun.oss.OSSClient;
 import com.aliyun.oss.OSSClientBuilder;
 import com.aliyun.oss.model.ObjectMetadata;
 import com.aliyun.oss.model.PutObjectRequest;
@@ -14,6 +15,7 @@ import jakarta.annotation.PostConstruct;
 import lombok.Data;
 import lombok.RequiredArgsConstructor;
 import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.stereotype.Component;
@@ -28,6 +30,7 @@ import java.time.LocalDateTime;
  * @author haoxr
  * @since 2.3.0
  */
+@Slf4j
 @Component
 @ConditionalOnProperty(value = "oss.type", havingValue = "aliyun")
 @ConfigurationProperties(prefix = "oss.aliyun")
@@ -55,13 +58,21 @@ public class AliyunFileService implements FileService {
 
     @PostConstruct
     public void init() {
-        aliyunOssClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+        try {
+            aliyunOssClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+            log.info("阿里云OSS客户端初始化成功,endpoint: {}, bucketName: {}", endpoint, bucketName);
+        } catch (Exception e) {
+            log.error("阿里云OSS客户端初始化失败: ", e);
+        }
     }
 
     @Override
     @SneakyThrows
     public FileInfo uploadFile(MultipartFile file) {
-
+        // 检查客户端是否初始化成功
+        if (aliyunOssClient == null) {
+            throw new RuntimeException("阿里云OSS客户端未正确初始化,请检查配置");
+        }
         // 获取文件名称
         String originalFilename = file.getOriginalFilename();
         // 生成文件名(日期文件夹)
@@ -78,8 +89,10 @@ public class AliyunFileService implements FileService {
             PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileName, inputStream, metadata);
             // 上传文件
             aliyunOssClient.putObject(putObjectRequest);
+            log.info("文件上传成功: {}", fileName);
         } catch (Exception e) {
-            throw new RuntimeException("文件上传失败");
+            log.error("文件上传失败: ", e);
+            throw new RuntimeException("文件上传失败: " + e.getMessage());
         }
         // 获取文件访问路径
         String fileUrl = "https://" + bucketName + "." + endpoint + "/" + fileName;
@@ -91,10 +104,16 @@ public class AliyunFileService implements FileService {
 
     @Override
     public boolean deleteFile(String filePath) {
-        Assert.notBlank(filePath, "删除文件路径不能为空");
-        String fileHost = "https://" + bucketName + "." + endpoint; // 文件主机域名
-        String fileName = filePath.substring(fileHost.length() + 1); // +1 是/占一个字符,截断左闭右开
-        aliyunOssClient.deleteObject(bucketName, fileName);
-        return true;
+        try {
+            Assert.notBlank(filePath, "删除文件路径不能为空");
+            String fileHost = "https://" + bucketName + "." + endpoint; // 文件主机域名
+            String fileName = filePath.substring(fileHost.length() + 1); // +1 是/占一个字符,截断左闭右开
+            aliyunOssClient.deleteObject(bucketName, fileName);
+            log.info("文件删除成功: {}", fileName);
+            return true;
+        } catch (Exception e) {
+            log.error("文件删除失败: ", e);
+            return false;
+        }
     }
 }

+ 6 - 2
src/main/java/com/zsElectric/boot/plugin/mybatis/MyMetaObjectHandler.java

@@ -1,6 +1,7 @@
 package com.zsElectric.boot.plugin.mybatis;
 
 import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
+import com.zsElectric.boot.security.util.SecurityUtils;
 import org.apache.ibatis.reflection.MetaObject;
 import org.springframework.stereotype.Component;
 
@@ -16,24 +17,27 @@ import java.time.LocalDateTime;
 public class MyMetaObjectHandler implements MetaObjectHandler {
 
     /**
-     * 新增填充创建时间
+     * 新增填充创建时间和创建人
      *
      * @param metaObject 元数据
      */
     @Override
     public void insertFill(MetaObject metaObject) {
         this.strictInsertFill(metaObject, "createTime", LocalDateTime::now, LocalDateTime.class);
+        this.strictInsertFill(metaObject, "createBy", SecurityUtils::getUserId, Long.class);
         this.strictUpdateFill(metaObject, "updateTime", LocalDateTime::now, LocalDateTime.class);
+        this.strictUpdateFill(metaObject, "updateBy", SecurityUtils::getUserId, Long.class);
     }
 
     /**
-     * 更新填充更新时间
+     * 更新填充更新时间和更新人
      *
      * @param metaObject 元数据
      */
     @Override
     public void updateFill(MetaObject metaObject) {
         this.strictUpdateFill(metaObject, "updateTime", LocalDateTime::now, LocalDateTime.class);
+        this.strictUpdateFill(metaObject, "updateBy", SecurityUtils::getUserId, Long.class);
     }
 
 }

+ 1 - 2
src/main/resources/application-dev.yml

@@ -137,7 +137,6 @@ security:
       - /api/v1/auth/captcha  # 验证码接口
     # 额外需要检查的请求头(默认已检查 User-Agent、Referer、X-Forwarded-For)
     check-headers:
-      - Cookie
       - Referer
       - X-Forwarded-For
 
@@ -176,7 +175,7 @@ oss:
     # 凭据密钥
     access-key-secret: xJkoJR1ILpXNSF2ERnxNq71UZTQNcB
     # 存储桶名称
-    bucket-name: zsElectric
+    bucket-name: national-motion
   # 本地存储
   local:
     # 文件存储路径 请注意下,mac用户请使用 /Users/your-username/your-path/,否则会有权限问题,windows用户请使用 D:/your-path/

+ 5 - 5
src/main/resources/application-prod.yml

@@ -113,7 +113,7 @@ security:
 # 文件存储配置
 oss:
   # OSS 类型 (目前支持aliyun、minio)
-  type: minio
+  type: aliyun
   # MinIO 对象存储服务
   minio:
     # 服务Endpoint
@@ -129,13 +129,13 @@ oss:
   # 阿里云OSS对象存储服务
   aliyun:
     # 服务Endpoint
-    endpoint: oss-cn-hangzhou.aliyuncs.com
+    endpoint: http://oss-cn-beijing.aliyuncs.com
     # 访问凭据
-    access-key-id: your-access-key-id
+    access-key-id: LTAI5tJscqbev7wSugGCrEtt
     # 凭据密钥
-    access-key-secret: your-access-key-secret
+    access-key-secret: xJkoJR1ILpXNSF2ERnxNq71UZTQNcB
     # 存储桶名称
-    bucket-name: default
+    bucket-name: zs-electric
   # 本地存储
   local:
     # 文件存储路径 请注意下,mac用户请使用 /Users/your-username/your-path/,否则会有权限问题,windows用户请使用 D:/your-path/

+ 1 - 1
src/main/resources/application.yml

@@ -2,7 +2,7 @@ spring:
   application:
     name: zsElectric-boot
   profiles:
-    active: prod
+    active: dev
   config:
     import: classpath:codegen.yml
   servlet:

+ 6 - 0
src/main/resources/logback-spring.xml

@@ -61,4 +61,10 @@
             <appender-ref ref="FILE"/>
         </root>
     </springProfile>
+
+    <!-- 当没有激活特定profile时的默认配置 -->
+    <root level="INFO">
+        <appender-ref ref="CONSOLE"/>
+        <appender-ref ref="FILE"/>
+    </root>
 </configuration>

+ 2 - 1
src/main/resources/mapper/business/AdvertisingMapper.xml

@@ -19,8 +19,9 @@
                 is_deleted
         FROM
             c_advertising
-        <where>
+        <where> is_deleted = 0
         </where>
+        ORDER BY sort DESC
     </select>
 
 </mapper>

+ 2 - 1
src/main/resources/mapper/business/BannerInfoMapper.xml

@@ -19,8 +19,9 @@
                 is_deleted
         FROM
             c_banner_info
-        <where>
+        <where> is_deleted = 0
         </where>
+        ORDER BY sort DESC
     </select>
 
 </mapper>

+ 15 - 15
src/main/resources/mapper/business/UserFeedbackMapper.xml

@@ -5,23 +5,23 @@
     <!-- 获取用户反馈分页列表 -->
     <select id="getUserFeedbackPage" resultType="com.zsElectric.boot.business.model.vo.UserFeedbackVO">
         SELECT
-                id,
-                type,
-                describe,
-                files_url,
-                contact_way,
-                reply,
-                user_id,
-                reply_time,
-                reply_status,
-                create_time,
-                create_by,
-                update_time,
-                update_by,
-                is_deleted
+        id,
+        type,
+        `desc`,
+        images,
+        contact_way,
+        reply,
+        user_id,
+        reply_time,
+        reply_status,
+        create_time,
+        create_by,
+        update_time,
+        update_by,
+        is_deleted
         FROM
             c_user_feedback
-        <where>
+        <where> is_deleted = 0
         </where>
     </select>