Class FileSecurityValidator

java.lang.Object
tech.riemann.nif.starter.file.FileSecurityValidator

public class FileSecurityValidator extends Object
文件上传安全校验器

提供多维度的文件上传安全检查,所有维度交叉联动而非独立放行:

  1. 非空校验——拒绝零字节文件;
  2. 文件大小校验——读取真实字节数(而非仅 MultipartFile.getSize() 声明值),并支持上限与下限;
  3. 文件名安全性——空名/超长/XSS 攻击字符/路径穿越语义检测;
  4. 扩展名校验——黑名单优先、白名单次之;
  5. MIME 内容校验——基于 Apache Tika 对真实文件内容检测,与扩展名交叉比对;
  6. 扩展名-内容一致性——扩展名声明的类型与内容真实类型不符(伪装文件)直接拒绝;
  7. 落盘路径校验——
    invalid reference
    #validateStoredPath(Path)
    基于 getCanonicalPath() 检测软链接与路径穿越。

与早期版本的关键差异: 早期版本在校验链中扩展名白名单命中即 return true,导致后续 MIME 内容检测被短路跳过, 攻击者可把 evil.exe 改名 evil.png 并塞入 PNG 头绕过内容检测。 本版本将扩展名与 MIME 改为双重必须都通过,并额外校验二者语义一致性。

失败处理:validate(MultipartFile) 在任一维度不通过时抛出 FileValidationException (携带细分错误码,由全局异常处理器统一映射为 400);若调用方希望自行处理失败,可使用 validateDetailed(MultipartFile) 获取 FileValidationResult。

Author:
kerbores(kerbores@gmail.com)
  • Constructor Details

    • FileSecurityValidator

      public FileSecurityValidator(Set<String> allowedMimeTypes, long maxSize)
      兼容构造(早期两参版本)
      Parameters:
      allowedMimeTypes - 允许的 MIME 类型
      maxSize - 最大字节数
    • FileSecurityValidator

      public FileSecurityValidator(Set<String> allowedMimeTypes, Set<String> allowedExtensions, Set<String> blockedExtensions, long maxSize, boolean checkFilenameXss, boolean checkPathTraversal, int maxFilenameLength)
      兼容构造(早期七参版本)
  • Method Details

    • validate

      public boolean validate(org.springframework.web.multipart.MultipartFile file) throws IOException
      校验文件(失败抛异常)
      Parameters:
      file - 上传的文件
      Returns:
      校验通过返回 true
      Throws:
      FileValidationException - 任一维度不通过
      IOException - 读取文件流时发生异常
    • validateDetailed

      public FileValidationResult validateDetailed(org.springframework.web.multipart.MultipartFile file) throws IOException
      校验文件(返回结果对象,不抛异常)
      Parameters:
      file - 上传的文件
      Returns:
      校验结果
      Throws:
      IOException - 读取文件流时发生异常
    • validateStoredPath

      public FileValidationResult validateStoredPath(Path storedPath, Path allowedBaseDir) throws IOException
      校验已落盘文件的存储路径安全性

      基于 Path.toRealPath(LinkOption...) /

      invalid reference
      Files#getCanonicalPath
      解析真实路径, 检测软链接逃逸与相对路径穿越——上传瞬间的文件名校验无法覆盖落盘后的真实路径, 业务层在完成文件写入后调用本方法对最终存储路径做最后一道防线。
      Parameters:
      storedPath - 已落盘文件的真实路径
      allowedBaseDir - 允许存储的根目录(规范化后),若为空则不限制目录
      Returns:
      校验结果
      Throws:
      IOException - 路径解析失败