首页 > 代码库 > java 附件上传时后台验证上传文件的合法性
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 = http://www.mamicode.com/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 =http://www.mamicode.com/= 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 =http://www.mamicode.com/ null ; String filePath = "D:/1.mhtml" ; try { is = new FileInputStream(filePath); byte [] b = new byte [ 4 ]; is.read(b, 0 , b.length); value = http://www.mamicode.com/bytesToHexString(b); } catch (Exception e) { } finally { if ( null != is) { try { is.close(); } catch (IOException e) { } } } System.out.println(value); } } |
用这种方法可以防止用户恶意更改文件后缀伪造合法上传文件的现象。
java 附件上传时后台验证上传文件的合法性
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。