web安全——判断文件流的文件上传解决上传漏洞
web安全——判断文件流的文件上传解决上传漏洞
主要实现的功能:
- 读取文件流来识别文件格式,判断上传的文件是否是jsp、js、exe等可执行文件。
- 根据日期分文件存放
防止文件名冲突
package cn.jiangdoc.utils.file;
import cn.jiangdoc.entity.Result;
import cn.jiangdoc.utils.FileType;
import cn.jiangdoc.utils.FileUtil;import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;@RestController
public class FileController {/** * 单文件上传 * * @param file * @param request * @return */
@RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
public Result uploadFile(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
// ------------------判断文件流类型的代码---------------
FileType fileType = null;
try {
fileType = FileUtil.getFileType(file.getInputStream());
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (fileType == null) {
// 非图片格式
return new Result(false, "非法文件!");
}
// -----------------end------------------------------
//文件的扩展名
String originalFilename = file.getOriginalFilename();
String extName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSS");
String res = sdf.format(new Date());
// 新文件名
String newFileName = "sliver" + res +"."+ extName;
// upload文件夹位置,webapp下
String rootPath = request.getSession().getServletContext().getRealPath("upload/");
//获取协议名+域名+端口号+项目名 = http+"://"+localhost+":"+8080+/booksystem
String url = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath();
try {
// 创建年月文件夹
Calendar date = Calendar.getInstance();
File dateDirs = new File(date.get(Calendar.YEAR) + File.separator + (date.get(Calendar.MONTH) + 1));
// 新文件
File newFile = new File(rootPath + File.separator + dateDirs + File.separator + newFileName);
// 判断目标文件所在目录是否存在
if (!newFile.getParentFile().exists()) {
// 如果目标文件所在的目录不存在,则创建父目录
newFile.getParentFile().mkdirs();
}
// 将内存中的数据写入磁盘
file.transferTo(newFile);
// 完整的url
String fileUrl = url + "/upload/" + date.get(Calendar.YEAR) + "/" + (date.get(Calendar.MONTH) + 1) + "/" + newFileName;
return new Result(true, fileUrl);
} catch (Exception e) {
e.printStackTrace();
return new Result(false, "上传失败");
}
}
/** * 多文件上传 * * @param files * @param request * @return */
@RequestMapping(value = "/uploadFiles", method = RequestMethod.POST)
public Result uploadFiles(@RequestParam("files") MultipartFile[] files, HttpServletRequest request) {
//判断file数组不能为空并且长度大于0
if (files != null && files.length > 0) {
try {
//循环获取file数组中得文件
String str = "[";
for (int i = 0; i < files.length; i++) {
Result result = uploadFile(files[i], request);
if (result.isFlag()) {
str += "{\"id\":" + i + ",\"url\":\"" + result.getMsg() + "\"},";
}
}
str = str.substring(0, str.lastIndexOf(","));
str += "]";
return new Result(true, str);
} catch (Exception e) {
e.printStackTrace();
return new Result(false, "[]");
}
} else
return null;
}
}
文件工具类
package cn.jiangdoc.utils.file;
import java.io.IOException;
import java.io.InputStream;
public class FileUtil {
/** * 判断文件是图片格式 * * @param is * @return * @throws IOException */
public static FileType getFileType(InputStream is) throws IOException {
byte[] src = new byte[28];
is.read(src, 0, 28);
StringBuilder stringBuilder = new StringBuilder("");
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v).toUpperCase();
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
FileType[] fileTypes = FileType.values();
for (FileType fileType : fileTypes) {
if (stringBuilder.toString().startsWith(fileType.getValue())) {
return fileType;
}
}
return null;
}
}
受信任的文件类型
package cn.jiangdoc.utils;
public enum FileType {
/** * JPEG */
JPEG("FFD8FF", "jpg"),
/** * PNG */
PNG("89504E47", "png"),
/** * GIF */
GIF("47494638", "gif"),
/** * TIFF */
TIFF("49492A00"),
/** * Windows bitmap */
BMP("424D"),
/** * CAD */
DWG("41433130"),
/** * Adobe photoshop */
PSD("38425053"),
/** * Rich Text Format */
RTF("7B5C727466"),
/** * XML */
XML("3C3F786D6C"),
/** * HTML */
HTML("68746D6C3E"),
/** * Outlook Express */
DBX("CFAD12FEC5FD746F "),
/** * Outlook */
PST("2142444E"),
/** * doc;xls;dot;ppt;xla;ppa;pps;pot;msi;sdw;db */
OLE2("0xD0CF11E0A1B11AE1"),
/** * Microsoft Word/Excel */
XLS_DOC("D0CF11E0"),
/** * Microsoft Access */
MDB("5374616E64617264204A"),
/** * Word Perfect */
WPB("FF575043"),
/** * Postscript */
EPS_PS("252150532D41646F6265"),
/** * Adobe Acrobat */
PDF("255044462D312E"),
/** * Windows Password */
PWL("E3828596"),
/** * ZIP Archive */
ZIP("504B0304"),
/** * ARAR Archive */
RAR("52617221"),
/** * WAVE */
WAV("57415645"),
/** * AVI */
AVI("41564920"),
/** * Real Audio */
RAM("2E7261FD"),
/** * Real Media */
RM("2E524D46"),
/** * Quicktime */
MOV("6D6F6F76"),
/** * Windows Media */
ASF("3026B2758E66CF11"),
/** * MIDI */
MID("4D546864");
private String value = "";
private String ext = "";
FileType(String value) {
this.value = value;
}
FileType(String value, String ext) {
this(value);
this.ext = ext;
}
public String getExt() {
return ext;
}
public String getValue() {
return value;
}
}
解决。
还没有评论,来说两句吧...