• java 附件上传时后台验证上传文件的合法性


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    package com.huawei.ha.modmgr.util;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.HashMap;
    import java.util.Map;
     
    import org.apache.commons.fileupload.FileItem;
     
     
    import com.huawei.bass.query.core.config.BIPropertiesBean;
    /**
     * @Description: 处理上传附件,校验是否合法
     * 在服务器端判断文件类型的问题,故用获取文件头的方式,
     * 直接读取文件的前几个字节,来判断上传文件是否符合格式
     * @author: huangyawei
     * @Created 2013 2013-8-19下午18:58:15
     */
    public class CheckoutFileType {
        //记录各个文件头信息及对应的文件类型
        public static Map<String, String> mFileTypes = new HashMap<String, String>();
         
        //所有合法的文件后缀
        public static String res_fileType=BIPropertiesBean.getProperty("fileType",".mht.mhtml");
         
        static {
            // images          
            mFileTypes.put("FFD8FFE0"".jpg");
            mFileTypes.put("89504E47"".png");
            mFileTypes.put("47494638"".gif");
            mFileTypes.put("49492A00"".tif");
            mFileTypes.put("424D"".bmp");
             
            //PS和CAD
            mFileTypes.put("38425053"".psd");
            mFileTypes.put("41433130"".dwg"); // CAD
            mFileTypes.put("252150532D41646F6265",".ps");
             
            //办公文档类
            mFileTypes.put("D0CF11E0"".doc"); //ppt、doc、xls
            mFileTypes.put("504B0304"".docx");//pptx、docx、xlsx   
             
            /**注意由于文本文档录入内容过多,则读取文件头时较为多变-START**/
            mFileTypes.put("0D0A0D0A"".txt");//txt
            mFileTypes.put("0D0A2D2D"".txt");//txt
            mFileTypes.put("0D0AB4B4"".txt");//txt       
            mFileTypes.put("B4B4BDA8"".txt");//文件头部为汉字
            mFileTypes.put("73646673"".txt");//txt,文件头部为英文字母
            mFileTypes.put("32323232"".txt");//txt,文件头部内容为数字
            mFileTypes.put("0D0A09B4"".txt");//txt,文件头部内容为数字
            mFileTypes.put("3132330D"".txt");//txt,文件头部内容为数字     
            /**注意由于文本文档录入内容过多,则读取文件头时较为多变-END**/
     
             
            mFileTypes.put("7B5C727466"".rtf"); // 日记本
             
            mFileTypes.put("255044462D312E"".pdf");
             
            //视频或音频类
            mFileTypes.put("3026B275",".wma");
            mFileTypes.put("57415645"".wav");
            mFileTypes.put("41564920"".avi");
            mFileTypes.put("4D546864"".mid");
            mFileTypes.put("2E524D46"".rm");
            mFileTypes.put("000001BA"".mpg");
            mFileTypes.put("000001B3"".mpg");
            mFileTypes.put("6D6F6F76"".mov");
            mFileTypes.put("3026B2758E66CF11"".asf");
             
            //压缩包
            mFileTypes.put("52617221"".rar");    
            mFileTypes.put("1F8B08"".gz");
             
            //程序文件
            mFileTypes.put("3C3F786D6C"".xml");
            mFileTypes.put("68746D6C3E"".html");
            mFileTypes.put("7061636B"".java");
            mFileTypes.put("3C254020"".jsp");
            mFileTypes.put("4D5A9000"".exe");        
             
             
            mFileTypes.put("44656C69766572792D646174653A"".eml"); // 邮件
            mFileTypes.put("5374616E64617264204A"".mdb");//Access数据库文件
             
            mFileTypes.put("46726F6D"".mht");
            mFileTypes.put("4D494D45"".mhtml");
             
             
        }
     
         
         
        /**
         * 根据文件的输入流获取文件头信息
         *
         * @param filePath 文件路径
         * @return 文件头信息
         */
        public static String getFileType(InputStream  is) {
            byte[] b = new byte[4];
            if(is!=null){
                try {
                    is.read(b, 0, b.length);
                catch (IOException e) {
                    e.printStackTrace();
                }
            }              
           
           return mFileTypes.get(getFileHeader(b));
        }
     
         
        /**
         * 根据文件转换成的字节数组获取文件头信息
         *
         * @param filePath
         *            文件路径
         * @return 文件头信息
         */
        public static String getFileHeader(byte[] b) {     
            String value = bytesToHexString(b);
            return value;
        }
     
        /**
         * 将要读取文件头信息的文件的byte数组转换成string类型表示
         * 下面这段代码就是用来对文件类型作验证的方法,
         * 将字节数组的前四位转换成16进制字符串,并且转换的时候,要先和0xFF做一次与运算。
         * 这是因为,整个文件流的字节数组中,有很多是负数,进行了与运算后,可以将前面的符号位都去掉,
         * 这样转换成的16进制字符串最多保留两位,如果是正数又小于10,那么转换后只有一位,
         * 需要在前面补0,这样做的目的是方便比较,取完前四位这个循环就可以终止了
         * @param src要读取文件头信息的文件的byte数组
         * @return 文件头信息
         */
        private static String bytesToHexString(byte[] src) {
            StringBuilder builder = new StringBuilder();
            if (src == null || src.length <= 0) {
                return null;
            }
            String hv;
            for (int i = 0; i < src.length; i++) {
                // 以十六进制(基数 16)无符号整数形式返回一个整数参数的字符串表示形式,并转换为大写
                hv = Integer.toHexString(src[i] & 0xFF).toUpperCase();
                if (hv.length() < 2) {
                    builder.append(0);
                }
                builder.append(hv);
            }
             
            System.out.println("获取文件头信息:"+builder.toString());
             
            return builder.toString();
        }
     
         
        /**
         * 判断上传的文件是否合法
         * (一)、第一:检查文件的扩展名,
         * (二)、 第二:检查文件的MIME类型 。
         * @param attachDoc
         * @return boolean
         */
        public static boolean getUpFilelegitimacyFlag(FileItem attachDoc){
            boolean upFlag=false;//为真表示符合上传条件,为假表标不符合
            if(attachDoc!=null){           
                String attachName =attachDoc.getName();
                 
                System.out.println("#######上传的文件:"+attachName);
                 
                if(!"".equals(attachName)&&attachName!=null){
                     
                    /**返回在此字符串中最右边出现的指定子字符串的索引   **/                             
                    String sname = attachName.substring(attachName.lastIndexOf("."));
                     
                    /**统一转换为小写**/
                    sname=sname.toLowerCase();
                     
                    /**第一步:检查文件扩展名,是否符合要求范围**/
                    if(res_fileType.indexOf(sname)!=-1){
                        upFlag=true;
                    }
                     
                    /**
                     * 第二步:获取上传附件的文件头,判断属于哪种类型,并获取其扩展名         
                     * 直接读取文件的前几个字节,来判断上传文件是否符合格式
                     * 防止上传附件变更扩展名绕过校验
                     ***/    
                    if(upFlag){
                         
                        byte[] b = new byte[4];
                         
                         
                         
                        String req_fileType = null;
                        try {
                            req_fileType = getFileType(attachDoc.getInputStream());
                        catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }                  
                        System.out.println("///////用户上传的文件类型///////////"+req_fileType);
                        /**第三步:检查文件扩展名,是否符合要求范围**/
                        if(req_fileType!=null && !"".equals(req_fileType) && !"null".equals(req_fileType)){
                            /**第四步:校验上传的文件扩展名,是否在其规定范围内**/
                            if(res_fileType.indexOf(req_fileType)!=-1){                    
                                upFlag=true;
                            }else{
                                upFlag=false;
                            }
                        }else{
                            /**特殊情况校验,如果用户上传的扩展名为,文本文件,则允许上传-START**/
                            if(sname.indexOf(".txt")!=-1){
                                upFlag=true;
                            }else{
                                upFlag=false;
                            }
                            /**特殊情况校验,如果用户上传的扩展名为,文本文件,则允许上传-END**/
                        }
                    }                                      
                }      
            }
            return upFlag;
        }
         
        /**
         * 主函数,测试用
         * @param args
         * @throws Exception
         */
        public static void main(String[] args) throws Exception {
            //final String fileType = getFileType("D:/BICP-HUAWEI.mht");
             
            FileInputStream is = null;
            String value = null;
             
            String filePath = "D:/1.mhtml";
            try {
                is = new FileInputStream(filePath);
                byte[] b = new byte[4];
                is.read(b, 0, b.length);
                value = bytesToHexString(b);
            catch (Exception e) {
            finally {
                if (null != is) {
                    try {
                        is.close();
                    catch (IOException e) {
                    }
                }
            }
     
            System.out.println(value);
        }
    }

    用这种方法可以防止用户恶意更改文件后缀伪造合法上传文件的现象。

  • 相关阅读:
    jdk源码阅读笔记之java集合框架(四)(LinkedList)
    jdk源码阅读笔记之java集合框架(二)(ArrayList)
    jdk源码阅读笔记之java集合框架(三)(modCount)
    java文件拷贝的一点思考
    mac(10.11.5 )安装pt-query-digest所遇问题总结
    关于springboot启动所需所有jar包详解
    volatile的一点理解
    java 虚拟机自动内存管理
    虚拟机运行时数据区划分
    笔记本连上wifi(WiFi完全没问题)却无法上网
  • 原文地址:https://www.cnblogs.com/bojuetech/p/5938928.html
Copyright © 2020-2023  润新知