SpringBoot如何驗證用戶上傳的圖片資源

這篇文章主要介紹了在SpringBoot中驗證用戶上傳的圖片資源,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑑價值,需要的朋友可以參考下

SpringBoot如何驗證用戶上傳的圖片資源SpringBoot如何驗證用戶上傳的圖片資源

允許用戶上傳圖片資源(頭像,發帖)是APP常見的需求,特別需要把用戶的資源IO到磁盤情況下,需要防止壞人提交一些非法的文件,例如木馬,webshell,可執行程序等等。這類非法文件不僅會導致客戶端圖片資源顯示失敗,而且還會給服務器帶來安全問題。

通過文件後綴判斷文件的合法性

這種方式比較常見,也很簡單,是目前大多數APP選擇的做法。

public Object upload (@RequestParam("file") MultipartFile multipartFile) throws IllegalStateException, IOException {
     
    // 原始文件名稱
    String fileName = multipartFile.getOriginalFilename();
     
    // 解析到文件後綴,判斷是否合法
    int index = fileName.lastIndexOf(".");
    String suffix = null;
    if (index == -1 || (suffix = fileName.substring(index + 1)).isEmpty()) {
        return "文件後綴不能爲空";
    }
     
    // 允許上傳的文件後綴列表
    Set allowSuffix = new HashSet<>(Arrays.asList("jpg", "jpeg", "png", "gif"));
    if (!allowSuffix.contains(suffix.toLowerCase())) {
        return "非法的文件,不允許的文件類型:" + suffix;
    }
     
    // 序列化到磁盤中的文件上傳目錄, /upload
    // FileCopyUtils.copy 方法會自動關閉流資源
    FileCopyUtils.copy(multipartFile.getInputStream(), Files.newOutputStream(Paths.get("D://upload", fileName), StandardOpenOption.CREATE_NEW));
     
    // 返回相對訪問路徑,文件名極有可能帶中文或者空格等字符,進行uri編碼
    return  "/" + UriUtils.encode(fileName, StandardCharsets.UTF_8);
}
使用 ImageIO 判斷是否是圖片

這個方法就比較嚴格了,在判斷後綴的基礎上,使用Java的ImageIO類去加載圖片,嘗試讀取其寬高信息,如果不是合法的圖片資源。則無法讀取到這兩個數據。就算是把非法文件修改了後綴,也可以檢測出來。

public Object upload (@RequestParam("file") MultipartFile multipartFile) throws IllegalStateException, IOException {
     
    // 原始文件名稱
    String fileName = multipartFile.getOriginalFilename();
     
    // 解析到文件後綴
    int index = fileName.lastIndexOf(".");
    String suffix = null;
    if (index == -1 || (suffix = fileName.substring(index + 1)).isEmpty()) {
        return "文件後綴不能爲空";
    }
     
    // 允許上傳的文件後綴列表
    Set allowSuffix = new HashSet<>(Arrays.asList("jpg", "jpeg", "png", "gif"));
    if (!allowSuffix.contains(suffix.toLowerCase())) {
        return "非法的文件,不允許的文件類型:" + suffix;
    }
     
    // 臨時文件
    File tempFile = new File(System.getProperty("java.io.tmpdir"), fileName);
     
    try {
        // 先把文件序列化到臨時目錄
        multipartFile.transferTo(tempFile);
        try {
            // 嘗試IO文件,判斷文件的合法性
            BufferedImage  bufferedImage = ImageIO.read(tempFile);
            bufferedImage.getWidth();
            bufferedImage.getHeight();
        } catch (Exception e) {
            // IO異常,不是合法的圖片文件,返回異常信息
            return "文件不是圖片文件";
        }
        // 複製到到上傳目錄
        FileCopyUtils.copy(new FileInputStream(tempFile), Files.newOutputStream(Paths.get("D://upload", fileName), StandardOpenOption.CREATE_NEW));
        // 返回相對訪問路徑
        return  "/" + UriUtils.encode(fileName, StandardCharsets.UTF_8);
    } finally {
        // 響應客戶端後,始終刪除臨時文件
        tempFile.delete();
    }
}
總結

使用ImageIo的方式更爲保險,但是需要多幾次IO操作。比較消耗性能。而且今天APP大都是用雲存儲服務,類似於阿里雲的OSS。直接就把客戶端上傳的文件PUT到了雲端,纔不管用戶上傳的圖片是不是真正的圖片,非法上傳,最多導致客戶端不能顯示而已,但是威脅不了服務器的安全。

本文地址:https://www.linuxprobe.com/springboot-java-imageio.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章