当前位置: 首页 > news >正文

java-springboot图片上传校验之只允许上传png、jpg、jpeg这三种类型,且文件大小不能超过10M,且检查不能是脚本或者有害文件或可行性文件

方案优势

  1. 四重安全校验

    • 文件扩展名检查
    • MIME类型检测(使用Apache Tika)
    • 文件头特征验证
    • 可执行文件特征检测
  2. 两种集成方式

    • AOP切面:自动拦截所有包含MultipartFile参数的方法
    • 手动调用:灵活控制校验时机
  3. 防御措施

    • 使用try-with-resources确保流关闭
    • 精确的文件头特征检查(防御伪造文件)
    • 统一的异常处理机制

需要引入依赖

 

<dependency><groupId>org.apache.tika</groupId><artifactId>tika-core</artifactId><version>2.7.0</version>
</dependency>
import org.apache.tika.Tika;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;public class ImageFileValidator {// 允许的MIME类型(使用Set提升查询性能)private static final Set<String> ALLOWED_MIME_TYPES = new HashSet<>(Arrays.asList("image/png","image/jpeg","image/jpg"));// 允许的文件扩展名private static final Set<String> ALLOWED_EXTENSIONS = new HashSet<>(Arrays.asList("png", "jpg", "jpeg"));// 最大文件大小(10MB)private static final long MAX_FILE_SIZE = 10 * 1024 * 1024;// 文件头特征检查(PNG/JPG/JPEG)private static final byte[][] IMAGE_MAGIC_NUMBERS = {{(byte) 0x89, 0x50, 0x4E, 0x47}, // PNG{(byte) 0xFF, (byte) 0xD8, (byte) 0xFF}, // JPEG/JPG};/*** 通用图片文件验证* @param file 上传的文件* @throws IOException 文件读取异常* @throws IllegalArgumentException 校验失败时抛出*/public static void validateImageFile(MultipartFile file) throws IOException, IllegalArgumentException {// 基础检查if (file == null || file.isEmpty()) {throw new IllegalArgumentException("文件不能为空");}// 检查文件大小if (file.getSize() > MAX_FILE_SIZE) {throw new IllegalArgumentException("文件大小不能超过10MB");}// 检查文件扩展名String originalFilename = file.getOriginalFilename();if (originalFilename == null) {throw new IllegalArgumentException("文件名无效");}String fileExtension = getFileExtension(originalFilename).toLowerCase();if (!ALLOWED_EXTENSIONS.contains(fileExtension)) {throw new IllegalArgumentException("仅支持PNG、JPG、JPEG格式文件");}// 使用Tika检测真实MIME类型(防御伪造扩展名)try (InputStream is = file.getInputStream()) {String detectedMimeType = new Tika().detect(is);if (!ALLOWED_MIME_TYPES.contains(detectedMimeType.toLowerCase())) {throw new IllegalArgumentException("非法的文件类型");}// 检查文件头特征if (!isValidImageHeader(is)) {throw new IllegalArgumentException("非法的图片文件格式");}// 恶意文件检测checkForExecutableContent(is);}}/*** 获取文件扩展名*/private static String getFileExtension(String filename) {int lastDot = filename.lastIndexOf(".");return lastDot == -1 ? "" : filename.substring(lastDot + 1);}/*** 验证文件头是否符合图片格式*/private static boolean isValidImageHeader(InputStream is) throws IOException {is.mark(10); // 标记以便重置byte[] header = new byte[4];if (is.read(header) != header.length) {return false;}is.reset();// 检查PNG头if (Arrays.equals(Arrays.copyOf(header, 4), IMAGE_MAGIC_NUMBERS[0])) {return true;}// 检查JPEG头return Arrays.equals(Arrays.copyOf(header, 3), IMAGE_MAGIC_NUMBERS[1]);}/*** 检查可执行文件特征*/private static void checkForExecutableContent(InputStream is) throws IOException {is.mark(1024);byte[] buffer = new byte[1024];int bytesRead = is.read(buffer);is.reset();if (bytesRead > 0) {// PE文件头检查(Windows可执行文件)if (bytesRead > 60 && buffer[0] == 0x4D && buffer[1] == 0x5A) {throw new IllegalArgumentException("检测到潜在有害文件内容");}// ELF文件头检查(Linux可执行文件)if (bytesRead > 4 && buffer[0] == 0x7F && buffer[1] == 0x45 && buffer[2] == 0x4C && buffer[3] == 0x46) {throw new IllegalArgumentException("检测到潜在有害文件内容");}}}
}

文章转载自:

http://2isXRAVj.wcghr.cn
http://0sLADpYo.wcghr.cn
http://SNSLsJke.wcghr.cn
http://JvBtcuqM.wcghr.cn
http://C9EmqlZq.wcghr.cn
http://FwRGhKUh.wcghr.cn
http://VMrAtrzi.wcghr.cn
http://apv6mlF2.wcghr.cn
http://4Qpn7nsX.wcghr.cn
http://tgNV70Su.wcghr.cn
http://qM1S9siw.wcghr.cn
http://hO1DiTbD.wcghr.cn
http://uJgWrq1A.wcghr.cn
http://fRpWY5BX.wcghr.cn
http://lSIrX6Y1.wcghr.cn
http://CTm9zZTz.wcghr.cn
http://568hRL0j.wcghr.cn
http://kxB2wfmL.wcghr.cn
http://BgM82qQ0.wcghr.cn
http://qsSiv6vZ.wcghr.cn
http://SZgUreA3.wcghr.cn
http://TWhmM7yE.wcghr.cn
http://yssBPofL.wcghr.cn
http://CToOElLV.wcghr.cn
http://5h4q2t9o.wcghr.cn
http://w5DymAwN.wcghr.cn
http://nwo9HT0S.wcghr.cn
http://42I526m4.wcghr.cn
http://9JJIjhkc.wcghr.cn
http://6D3Mca3r.wcghr.cn
http://www.dtcms.com/a/228963.html

相关文章:

  • 缩量和放量指的是什么?
  • Tailwind CSS 实战:基于 Kooboo 构建 AI 对话框页面(六):图片上传功能
  • Kafka集群部署(docker容器方式)SASL认证(zookeeper)
  • 前端基础之《Vue(18)—路由知识点》
  • OpenCV 滑动条调整图像对比度和亮度
  • Spring @Autowired自动装配的实现机制
  • Redis配置了在磁盘上保存 RDB 快照,但目前无法持久化到磁盘
  • 数据结构:递归:自然数之和
  • [Java恶补day14] 56. 合并区间
  • 悟饭游戏厅苹果版(悟饭掌悦)|iOS游戏社区手柄工具
  • 【25.06】fabric进行caliper测试加环境部署
  • Vue-ref 与 props
  • browser-use Agent 日志链路分析
  • 1.1Nodejs和浏览器中的二进制处理
  • linux常用特殊字符
  • vue路由的使用与鉴权
  • 健康管理软件+AI技术:打造健康管理方案
  • CppCon 2014 学习:Return values take a ”closure” walk
  • 安全-JAVA开发-第一天
  • 哪些IT运维工具支持自定义监控项?
  • 网络编程(计算机网络基础)
  • 力扣刷题Day 69:搜索二维矩阵(74)
  • LeetCode刷题 -- 542. 01矩阵 基于 DFS 更新优化的多源最短路径实现
  • WebFuture 系列产品 15.2.4 发布公告
  • 黑马Java面试笔记之 消息中间件篇(Kafka)
  • 【动手学机器学习】第三章模式识别与机器学习经典算法——k 近邻算法
  • 2025年AIR SCI1区TOP,多策略增强蜣螂算法MDBO+实际工程问题,深度解析+性能实测
  • 谷歌地图高清卫星地图2026中文版下载|谷歌地图3D卫星高清版 V7.3.6.9796 最新免费版下载 - 前端工具导航
  • 让AI弹琴作曲不再是梦:Python+深度学习玩转自动化音乐创作
  • 【Mysql】隐式转换造成索引失效