Java校驗(yàn)上傳圖片文件是否含有木馬的兩種方式

這兩天開(kāi)發(fā)一個(gè)app遇到了上傳文件的安全問(wèn)題,在這里記錄下來(lái),彌補(bǔ)自己只有魚(yú)的記憶的缺陷,也希望有人能夠提供更好的思路去解決文件上傳的安全問(wèn)題.
下面這個(gè)類是文件上傳的公共方法,ToolUtils判斷的是文件的類型(jpg/png等),這樣的做法根本不能避免上傳的文件不是木馬.下面引入兩種方式,調(diào)用時(shí)候只需要引用一種即可.
  • private String executeUpload(String uploadDir,MultipartFile file) throws Exception {
         // 文件后綴名
         String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
         // 判斷后綴名是否合法
         String suffixs = suffix.substring(1, suffix.length());
         boolean isImage = ToolUtils.isImage(suffixs);
         if(!isImage) {
             logger.error("the transfer file is not a image!");
             throw new FileException("上傳非法文件!");
         }
         // 上傳文件名
         String fileName = UUID.randomUUID() + suffix;
         InputStream inputStream = file.getInputStream();
         // 第二種,判斷文件是否含有木馬(讀取流)
         // boolean flag = FileUtil.isFile(inputStream);
         // if(!flag) {
         //  logger.error("the transfer file is not a image!");
         //  throw new FileException("上傳非法文件!");
         // }
         // 服務(wù)器端保存的文件對(duì)象
     
         // 第一種重寫(xiě)圖片引入
         try {
             ImageUtil.resize1(inputStream, fileName, uploadDir);
         } catch (Exception e) {
             logger.error("the transfer file is not a image!");
             throw new FileException("上傳非法文件!");
         }
         // File serverFile = new File(uploadDir + fileName);
         // 將上傳的文件寫(xiě)入到服務(wù)器端文件內(nèi)
         // file.transferTo(serverFile);
     
         return fileName;
     }
    
第一種是將出入的圖片重寫(xiě),實(shí)踐證明,不是圖片的文件會(huì)直接報(bào)錯(cuò),然后在executeUpload中被捕獲.是圖片但有腳本文件的文件會(huì)被重寫(xiě),腳本文件會(huì)被移除.
   *     public class ImageUtil {

            public static void resize1(InputStream inputStream, String fileName, String uploadDir) throws Exception  {
                if (inputStream == null) {
                    return;
                }
                BufferedImage src = ImageIO.read(inputStream);
                int old_w = src.getWidth();
                // 得到源圖寬
                int old_h = src.getHeight();
                // 得到源圖長(zhǎng)
                BufferedImage newImg = null;
                // 判斷輸入圖片的類型
                switch (src.getType()) {
                case 13:
                  // png,gif
                  newImg = new BufferedImage(old_w, old_h, BufferedImage.TYPE_4BYTE_ABGR);
                  break;
                default:
                  newImg = new BufferedImage(old_w, old_h, BufferedImage.TYPE_INT_RGB);
                  break;
                }
                Graphics2D g = newImg.createGraphics();
                // 從原圖上取顏色繪制新圖
                g.drawImage(src, 0, 0, old_w, old_h, null);
                g.dispose();
                // 根據(jù)圖片尺寸壓縮比得到新圖的尺寸
                newImg.getGraphics().drawImage(
                src.getScaledInstance(old_w, old_h, Image.SCALE_SMOOTH), 0,0, null);
                File newFile = new File(uploadDir+fileName);
                String endName = fileName.substring(fileName.lastIndexOf(".")+1).toLowerCase();
                ImageIO.write(newImg, endName, newFile);
          }
      }
第二種是將圖片流轉(zhuǎn)換成十六進(jìn)制的string字符進(jìn)行過(guò)濾,分辨是否含有高危字符.
  •  public static boolean isFile(InputStream inputStream) throws IOException {
          byte[] byteArray = IOUtils.toByteArray(inputStream);
          String str = bytesToHexString(byteArray);
          // 匹配16進(jìn)制中的 <% ( ) %> 
          // 匹配16進(jìn)制中的 <? ( ) ?> 
          // 匹配16進(jìn)制中的 <script | /script> 大小寫(xiě)亦可
          // 通過(guò)匹配十六進(jìn)制代碼檢測(cè)是否存在木馬腳本
          String pattern = "(3c25.*?28.*?29.*?253e)|(3c3f.*?28.*?29.*?3f3e)|(3C534352495054)|(2F5343524950543E)|(3C736372697074)|(2F7363726970743E)";
          Pattern mPattern = Pattern.compile(pattern);
          Matcher mMatcher = mPattern.matcher(str);
       
          // 查找相應(yīng)的字符串
          boolean flag = true;
          if(mMatcher.find()) {
              flag = false;
             //過(guò)濾java關(guān)鍵字(java import String print write( read() php request alert system)(暫時(shí)先這樣解決,這樣改動(dòng)最小,以后想后更好的解決方案再優(yōu)化)
              String keywordPattern = "(6a617661)|(696d706f7274)|(537472696e67)|(7072696e74)|(777269746528)|(726561642829)|(706870)|(72657175657374)|(616c657274)|(73797374656d)";
              Pattern keywordmPattern = Pattern.compile(keywordPattern);
              Matcher keywordmMatcher = keywordmPattern.matcher(str);
              if(keywordmMatcher.find()){
                  flag = false;
              }
          }
          return flag;
     }
    
希望以上代碼對(duì)您有幫助,也希望留下您對(duì)這方面更好的理解.
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,653評(píng)論 19 139
  • Java 語(yǔ)言支持的類型分為兩類:基本類型和引用類型。整型(byte 1, short 2, int 4, lon...
    xiaogmail閱讀 1,450評(píng)論 0 10
  • 一、Java 簡(jiǎn)介 Java是由Sun Microsystems公司于1995年5月推出的Java面向?qū)ο蟪绦蛟O(shè)計(jì)...
    子非魚(yú)_t_閱讀 4,564評(píng)論 1 44
  • 清波映照怒放模樣 緋紅臉頰難掩 幽情 詩(shī)人搔首華章 青燈下
    星空物語(yǔ)_07f5閱讀 163評(píng)論 0 0
  • 5.卜式的故事 皇帝又想起了卜式的話,于是將卜式找來(lái),任命他為中郎,并賜給他左庶長(zhǎng)的爵位和十頃田地,又將此事詔告天...
    張七公子閱讀 1,044評(píng)論 0 13

友情鏈接更多精彩內(nèi)容