10-java实现对上传文件做安全性检查

这篇具有很好参考价值的文章主要介绍了10-java实现对上传文件做安全性检查。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

对外接口支持文件上传功能时,为避免有人恶意上传有毒或者篡改程序的脚本,需要对上传的文件添加安全性校验。

1.文件后缀校验

文件首先校验直观文件上传格式,校验文件后缀是否符合业务要求。以MultipartFile类为例

        String fileName = file.getOriginalFilename();
        if (Strings.isEmpty(fileName)) {
            throw new RuntimeException("文件名未找到");
        }
        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
        if (!Objects.equal(suffix, "xls") && !Objects.equal(suffix, "xlsx")) {
            throw new RuntimeException("文件类型不正确,需要为xls或者xlsx");
        }

2.校验文件头

由于文件后缀可能涉及到篡改的情况出现,因此需要校验文件的魔数,也就是文件头。无论这个文件是否修改文件后缀,这个文件的文件头是不会改变的。下面是常用的文件头格式:

1.使用枚举类去校验

JPEG (jpg),文件头:FFD8FFE1
PNG (png),文件头:89504E47
GIF (gif),文件头:47494638
TIFF (tif),文件头:49492A00
Windows Bitmap (bmp),文件头:424D
CAD (dwg),文件头:41433130
Adobe Photoshop (psd),文件头:38425053
Rich Text Format (rtf),文件头:7B5C727466
XML (xml),文件头:3C3F786D6C
HTML (html),文件头:68746D6C3E
Email [thorough only] (eml),文件头:44656C69766572792D646174653A
Outlook Express (dbx),文件头:CFAD12FEC5FD746F
Outlook (pst),文件头:2142444E
MS Word/Excel (xls.or.doc),文件头:D0CF11E0
MS Access (mdb),文件头:5374616E64617264204A
WordPerfect (wpd),文件头:FF575043
Postscript (eps.or.ps),文件头:252150532D41646F6265
Adobe Acrobat (pdf),文件头:255044462D312E
Quicken (qdf),文件头:AC9EBD8F
Windows Password (pwl),文件头:E3828596
ZIP Archive (zip),文件头:504B0304
RAR Archive (rar),文件头:52617221
Wave (wav),文件头:57415645
AVI (avi),文件头:41564920
Real Audio (ram),文件头:2E7261FD
Real Media (rm),文件头:2E524D46
MPEG (mpg),文件头:000001BA
MPEG (mpg),文件头:000001B3
Quicktime (mov),文件头:6D6F6F76
Windows Media (asf),文件头:3026B2758E66CF11
MIDI (mid),文件头:4D546864

使用上面的文件头去校验的代码示例(这段代码参考:Java 实战系列·Magic 魔数获取文件类型):

1.魔数枚举类

public enum FileType {
    /**
     * JPEG
     */
    JPEG("JPEG", "FFD8FF"),

    /**
     * PNG
     */
    PNG("PNG", "89504E47"),

    /**
     * GIF
     */
    GIF("GIF", "47494638"),

    /**
     * TIFF
     */
    TIFF("TIFF", "49492A00"),

    /**
     * Windows bitmap
     */
    BMP("BMP", "424D"),

    /**
     * CAD
     */
    DWG("DWG", "41433130"),

    /**
     * Adobe photoshop
     */
    PSD("PSD", "38425053"),

    /**
     * Rich Text Format
     */
    RTF("RTF", "7B5C727466"),

    /**
     * XML
     */
    XML("XML", "3C3F786D6C"),

    /**
     * HTML
     */
    HTML("HTML", "68746D6C3E"),

    /**
     * Outlook Express
     */
    DBX("DBX", "CFAD12FEC5FD746F "),

    /**
     * Outlook
     */
    PST("PST", "2142444E"),

    /**
     * doc;xls;dot;ppt;xla;ppa;pps;pot;msi;sdw;db
     */
    OLE2("OLE2", "0xD0CF11E0A1B11AE1"),

    /**
     * Microsoft Word/Excel
     */
    XLS_DOC("XLS_DOC", "D0CF11E0"),

    /**
     * Microsoft Access
     */
    MDB("MDB", "5374616E64617264204A"),

    /**
     * Word Perfect
     */
    WPB("WPB", "FF575043"),

    /**
     * Postscript
     */
    EPS_PS("EPS_PS", "252150532D41646F6265"),

    /**
     * Adobe Acrobat
     */
    PDF("PDF", "255044462D312E"),

    /**
     * Windows Password
     */
    PWL("PWL", "E3828596"),

    /**
     * ZIP Archive
     */
    ZIP("ZIP", "504B0304"),

    /**
     * ARAR Archive
     */
    RAR("RAR", "52617221"),

    /**
     * WAVE
     */
    WAV("WAV", "57415645"),

    /**
     * AVI
     */
    AVI("AVI", "41564920"),

    /**
     * Real Audio
     */
    RAM("RAM", "2E7261FD"),

    /**
     * Real Media
     */
    RM("RM", "2E524D46"),

    /**
     * Quicktime
     */
    MOV("MOV", "6D6F6F76"),

    /**
     * Windows Media
     */
    ASF("ASF", "3026B2758E66CF11"),

    /**
     * MIDI
     */
    MID("MID", "4D546864");

    private String key;
    private String value;

    FileType(String key, String value) {
        this.key = key;
        this.value = value;
    }

    public String getValue() {
        return value;
    }
    public String getKey() {
        return key;
    }
}

2.获取文件头,并校验是否为Excel

public class FileUtil {

    /**
     * 获取文件投
     *
     * @param filePath 文件路径
     * @return 16 进制的文件投信息
     *
     * @throws IOException
     */
    private static String getFileHeader(String filePath) throws IOException {
        byte[] b = new byte[28];
        InputStream inputStream = new FileInputStream(filePath);
        inputStream.read(b, 0, 28);
        inputStream.close();
        return bytes2hex(b);
    }

    /**
     * 将字节数组转换成16进制字符串
     */
    private static String bytes2hex(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder("");
        if (src == null || src.length <= 0) {
            return null;
        }
        for (byte b : src) {
            int v = b & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }

    /**
     * 校验是否为excel
     *
     * @param filePath 文件路径
     * @return 文件类型
     *
     * @throws IOException
     */
    public static boolean checkIsExcel(String filePath) throws IOException {
        String fileHead = getFileHeader(filePath);
        if (null == fileHead || fileHead.length() == 0) {
            return false;
        }
        //校验是否为xls或者xlsx文件
        if (Objects.equal(fileHead, FileType.OLE2.getValue()) || Objects.equal(fileHead, FileType.XLS_DOC.getValue())) {
            return true;
        }
        return false;
    }
}

除了用上面的魔数头去校验,也可以用poi提供的枚举类FileMagic工具类去校验:

2.FileMagic校验文件头

FileMagic魔数值解释:

    OLE2(-2226271756974174256L),   //xls
    OOXML(new int[]{80, 75, 3, 4}), //xlsx, OOXML全称是Office Open XML,OOXML是由微软公司为Office 2007产品开发的技术规范,现已成为国际文档格式标准,兼容前国际标准ODF(Open Document Format)和中国文档标准UOF(Unified Office document Format)。
    XML(new int[]{60, 63, 120, 109, 108}),  //xml
    BIFF2(new int[]{9, 0, 4, 0, 0, 0, 63, 0}), //Excel 2 现在office已经不支持
    BIFF3(new int[]{9, 2, 6, 0, 0, 0, 63, 0}),//Excel 3现在office已经不支持
    BIFF4(new byte[][]{{9, 4, 6, 0, 0, 0, 63, 0}, {9, 4, 6, 0, 0, 0, 0, 1}}),//Excel 4 现在office已经不支持
    MSWRITE(new byte[][]{{49, -66, 0, 0}, {50, -66, 0, 0}}),  //微软原来的写入流,这个不清楚是否还能使用。
    RTF(new String[]{"{\\rtf"}),  //rtf
    PDF(new String[]{"%PDF"}), //pdf
    HTML(new String[]{"<!DOCTYP", "<html", "\n\r<html", "\r\n<html", "\r<html", "\n<html", "<HTML", "\r\n<HTML", "\n\r<HTML", "\r<HTML", "\n<HTML"}),  //HTML
    WORD2(new int[]{219, 165, 45, 0}),//word
    JPEG(new byte[][]{{-1, -40, -1, -37}, {-1, -40, -1, -32, 63, 63, 74, 70, 73, 70, 0, 1}, {-1, -40, -1, -18}, {-1, -40, -1, -31, 63, 63, 69, 120, 105, 102, 0, 0}}),//图片验证,jpeg格式
    GIF(new String[]{"GIF87a", "GIF89a"}),//图片验证,gif格式
    PNG(new int[]{137, 80, 78, 71, 13, 10, 26, 10}),//图片验证,png格式
    TIFF(new String[]{"II*\u0000", "MM\u0000*"}),//图片验证,tiff格式
    WMF(new int[]{215, 205, 198, 154}),//图片验证,wmf格式
    EMF(new int[]{1, 0, 0, 0, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 32, 69, 77, 70}),//图片验证,emf格式
    BMP(new int[]{66, 77}),//图片验证,nmp格式
    UNKNOWN(new byte[][]{new byte[0]});//未知魔数

使用魔数校验Excel文件代码:

 private static boolean checkIsExcel(InputStream inputStream) throws IOException {
 	//获取文件流的文件头
     FileMagic fileMagic = FileMagic.valueOf(inputStream);
     //判断Excel文件头是否符合xls或者xlsx
     if (Objects.equal(fileMagic, FileMagic.OLE2) || Objects.equal(fileMagic, FileMagic.OOXML)) {
         return true;
     }
     return false;
 }

3.校验文件大小

为了避免上传过大文件,影响服务器性能以及带宽。需要对文件大小进行校验,具体文件大小控制以业务为主。

4.示例

以校验Excel文件为例:文章来源地址https://www.toymoban.com/news/detail-441763.html

 /**
     * 校验文件
     *
     * @param file 文件
     * @param fileMaxSize  文件大小限制
     */
    public static void checkExcel(MultipartFile file, Double fileMaxSize) {
        // 文件类型判断 - 校验文件后缀
        String fileName = file.getOriginalFilename();
        if (Strings.isEmpty(fileName)) {
            throw new RuntimeException("文件名未找到");
        }
        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
        if (!Objects.equal(suffix, "xls") && !Objects.equal(suffix, "xlsx")) {
            throw new RuntimeException("文件类型不正确,需要为xls或者xlsx");
        }

        // 文件类型判断 - 校验文件头内容
        try (InputStream inputStream = file.getInputStream()) {
            // 获取到上传文件的文件头信息
            boolean isExcel = checkIsExcel(inputStream);
            if (!isExcel) {
                throw new RuntimeException("文件类型不正确,原文件类型需要为xls");
            }
        } catch (IOException e) {
            log.error("Get file input stream failed.", e);
            throw new RuntimeException("文件上传失败");
        }

        // 文件大小校验 - 单位:MB
        long fileBytes = file.getSize();
        double fileSize = (double) fileBytes / 1048576;
        if (fileSize <= 0) {
            throw new RuntimeException("文件内容为空");
        }
        if (fileSize > fileMaxSize) {
            throw new RuntimeException("文件上传内容大小超出限制");
        }
    }

    /**
     * 校验文件头
     *
     * @param inputStream
     * @return
     *
     * @throws IOException
     */
    private static boolean checkIsExcel(InputStream inputStream) throws IOException {
        FileMagic fileMagic = FileMagic.valueOf(inputStream);
        if (Objects.equal(fileMagic, FileMagic.OLE2) || Objects.equal(fileMagic, FileMagic.OOXML)) {
            return true;
        }
        return false;
    }

到了这里,关于10-java实现对上传文件做安全性检查的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 商用密码应用安全性评估----技术层面实现

    网络和通信安全        三个密码产品  SSL VPN IPSEC VPN  安全认证网关-----数字证书---双证书-----SM2签名  SM4加密   D 是否使用这些安全产品   A用的算法是否符合国家密码算法要求       K密钥管理是否安全(商用密码产品检测中心认证的)       对象:一般划分根据

    2024年02月16日
    浏览(52)
  • Java应用服务系统安全性,签名和验签浅析

    随着互联网的普及,分布式服务部署越来越流行,服务之间通信的安全性也是越来越值得关注。这里,笔者把应用与服务之间通信时,进行的的安全性相关, 加签 与 验签 ,进行了一个简单的记录。 网关服务接口,暴漏在公网,被非法调用? 增加了token安全验证,被抓包等

    2024年02月13日
    浏览(41)
  • 【Linux命令详解 | chmod命令】 chmod命令用于修改文件或目录的权限,保护文件安全性。

    在Ubuntu系统中, chmod 命令是一个强大的工具,用于修改文件或目录的权限,从而保护文件的安全性。通过适当配置权限,可以控制哪些用户或用户组可以访问、读取、写入或执行特定文件或目录。 chmod 命令是Linux/Unix系统中的基础命令之一,对于系统管理员和开发者来说都是

    2024年02月12日
    浏览(103)
  • java生成一个符合密码学和安全性的随机秘钥

    有时 我们在生成token 或者完成某种加密形式时会需要一个秘钥 但是 有些时候 项目开发并没有规定用什么秘钥 但是 秘钥都是要有一定格式规范的 我们可以通过以下代码生成一个随机秘钥 重点是 这种一定会符合密码学和安全规范

    2024年02月07日
    浏览(38)
  • PHP+SQL考勤系统安全性的设计与实现

    第一章 概 述 1.1  PHP的概念 PHP: Hypertext Preprocessor ( 超文本预处理器 ) 的缩写,它是一种服务器端的 HTML 脚本 / 编程语言 , 是一种简单的、 面向对象 的、解释型的、健壮的、安全的、性能非常之高的、独立于架构的、可移植的、动态的脚本语言

    2023年04月08日
    浏览(74)
  • 云计算与大数据平台:实现高度安全性的关键技术

    云计算和大数据平台在现代信息技术中扮演着越来越重要的角色。随着数据的产生和传输量日益增加,数据安全和系统安全成为了企业和个人最关注的问题。本文将从云计算与大数据平台的角度,深入探讨实现高度安全性的关键技术。 云计算是一种基于互联网的计算资源共享

    2024年04月27日
    浏览(45)
  • WebSocket与Shiro认证信息传递的实现与安全性探讨

    在现代Web应用程序中,WebSocket已经成为实时双向通信的重要组件。而Shiro作为一个强大的Java安全框架,用于处理身份验证、授权和会话管理。本文将探讨如何通过WebSocket与Shiro集成,实现认证信息的传递,并关注在这一过程中确保安全性的关键考虑因素。 步骤概述 WebSocket连接

    2024年01月25日
    浏览(44)
  • 如何使用Flask-Login来实现用户身份验证和安全性?

    当你想要在你的Flask应用中实现用户身份验证和安全性时,Flask-Login这个扩展将会是你的最佳伙伴。它提供了一组简单而强大的工具来处理用户登录、注销和其他安全相关的操作。下面,我将以一个新手的角度,用尽可能轻松的语气来解释如何使用Flask-Login。 首先,你需要在你

    2024年02月15日
    浏览(43)
  • C++中的网络编程和安全性:实现安全的Web应用程序和网络应用程序

    作者:禅与计算机程序设计艺术 《67. C++中的网络编程和安全性:实现安全的Web应用程序和网络应用程序》 1.1. 背景介绍 随着互联网的快速发展,网络应用程序在人们的生活和工作中扮演着越来越重要的角色,网络编程和安全性也成为了现代应用程序的重要组成部分。在网络

    2024年02月16日
    浏览(51)
  • 加密数据安全性的两大安全护盾-前向安全性与后向安全性详解

    在数字安全的世界里,加密技术是用来保护数据不被未经授权访问的重要机制。然而,即使使用了最强的加密算法,也不能保证永远是安全的。攻击者可能会在未来某个时间点获得了解密密钥,从而能够解密拦截的密文。为了解决这个问题,密码学引入了前向安全性(Forwar

    2024年02月04日
    浏览(66)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包