-----------------------------------------------------------------------------------------------------------------------------------
与同事讨论的文件上传安全问题:
1.老项目采用的上传至项目下某个目录的做法是很不安全的,容易被访问到上传文件,应当制定到项目之外的目录.
2.如果只使用一次,比如上传Excel导入数据,则可以不将文件保存到磁盘.
3.限制文件类型使用 后缀名 判断即可,因为只要黑客可以操作修改后缀名了,那改文件头之类的也可以被改回.
4.条件允许的话使用 minio存储系统,设置token 和有效时间,可增强安全性
5.新型的攻击方式改为攻击防护薄弱的客户端
----------------------------------------------------------------------------------------------------------------------------------------------------------
背景:公司老项目,使用的一个基于SSH的老框架二次开发,原框架封装的上传类没有限制文件类型,等保评测查出需要整改
思路:因为原上传类封装在jar包中不好处理,所以在web.xml中将处理上传的类改为自己编写的类
即:
<servlet> <servlet-name>fileUpload</servlet-name> <!-- <servlet-class>com.htsoft.core.web.servlet.FileUploadServlet</servlet-class> --> <!-- 替换htsoft封装的原有上传方法,加入对文件类型的过滤,只允许上传几种文件,防止恶意上传可执行文件 --> <servlet-class>com.htsoft.core.web.servlet.FileUploadServletNew</servlet-class> </servlet>
上传处理类
public class FileUploadServletNew extends HttpServlet{ private static final long serialVersionUID = 1L; private Log logger=LogFactory.getLog(FileUploadServletNew.class); @SuppressWarnings("unused") private ServletConfig servletConfig=null; private FileAttachService fileAttachService=(FileAttachService)AppUtil.getBean("fileAttachService"); private AppUserService appUserService = (AppUserService)AppUtil.getBean("appUserService"); private GlobalTypeService globalTypeService = (GlobalTypeService)AppUtil.getBean("globalTypeService"); private String uploadPath=""; // 上传文件的目录 private String tempPath=""; // 临时文件目录 private String fileCat="others"; @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("===========上传方法New==========="); String flexUserId = req.getParameter("flexUserId"); // flex中获取登录用户的id String fileTypeId = req.getParameter("fileTypeId"); // 附件类型id GlobalType globalType = null; if(StringUtils.isNotEmpty(fileTypeId)){ globalType = globalTypeService.get(new Long(fileTypeId)); } //指定保存至某个目录,若提交时,指定了该参数值,则表示保存的操作 String filePath=""; String fileId=""; req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); try { DiskFileItemFactory factory = new DiskFileItemFactory(); // 缓存大小 factory.setSizeThreshold(4096); factory.setRepository(new File(tempPath)); ServletFileUpload fu=new ServletFileUpload(factory); List<FileItem> fileItems = fu.parseRequest(req); //取得相关参数值 for(FileItem fi:fileItems){ if("file_cat".equals(fi.getFieldName())){ fileCat=fi.getString(); //break; } if("file_path".equals(fi.getFieldName())){ filePath=fi.getString(); } if("fileId".equals(fi.getFieldName())){ fileId=fi.getString(); } } logger.info("fileId:" + fileId); Iterator<FileItem> i = fileItems.iterator(); StringBuffer sb = new StringBuffer(""); StringBuffer sb1 = new StringBuffer(""); StringBuffer sb2 = new StringBuffer(""); sb = new StringBuffer("{\"success\":\"true\""); sb.append(",\"fileId\":["); //目前处理每次只上传一个文件 while(i.hasNext()) { FileAttach file=null; FileItem fi = (FileItem)i.next(); if(fi.getContentType()==null){ continue; } //返回文件名及路径及fileId. String path = fi.getName(); int start=path.lastIndexOf("\\"); //原文件名 String fileName=path.substring(start+1); //处理文件名,只允许xls,xlxs int hzmindex=fileName.lastIndexOf("."); String hzm = fileName.substring(hzmindex+1); if(!(hzm.equals("xls") || hzm.equals("xlsx"))){ System.out.println("=======文件类型错误,只允许上传Excel文件!========"); sb2.append("文件类型错误,只允许上传Excel文件!"); break; } String relativeFullPath=null; if(!"".equals(filePath)){ relativeFullPath=filePath; } else if(!"".equals(fileId)){ FileAttach fileAttach=fileAttachService.get(new Long(fileId)); relativeFullPath=fileAttach.getFilePath(); logger.info("exist filePath:" + relativeFullPath); } else{ relativeFullPath=fileCat+"/" + FileUtil.generateFilename(fileName); } int index=relativeFullPath.lastIndexOf("/"); File dirPath=new File(uploadPath+"/" + relativeFullPath.substring(0,index+1)); if(!dirPath.exists()){ dirPath.mkdirs(); } fi.write(new File(uploadPath+"/" + relativeFullPath)); if(!"".equals(filePath)){ file=fileAttachService.getByPath(filePath); file.setTotalBytes(fi.getSize()); file.setNote(getStrFileSize(fi.getSize())); fileAttachService.save(file); } if(!"".equals(fileId)){ file=fileAttachService.get(new Long(fileId)); file.setTotalBytes(fi.getSize()); file.setNote(getStrFileSize(fi.getSize())); fileAttachService.save(file); } if(file==null) { file=new FileAttach(); file.setCreatetime(new Date()); AppUser curUser = ContextUtil.getCurrentUser(); if(StringUtils.isNotEmpty("isFlex") && StringUtils.isNotEmpty(flexUserId)){ curUser = appUserService.get(new Long(flexUserId)); } if(curUser != null){ file.setCreator(curUser.getFullname()); file.setCreatorId(curUser.getUserId()); } else { file.setCreator("UNKown"); } int dotIndex=fileName.lastIndexOf("."); file.setExt(fileName.substring(dotIndex+1)); file.setFileName(fileName); file.setFilePath(relativeFullPath); file.setFileType(fileCat); if(globalType == null){ globalType = globalTypeService.findByFileType(fileCat); } if(globalType != null){ file.setGlobalType(globalType); } file.setTotalBytes(fi.getSize()); file.setNote(getStrFileSize(fi.getSize())); file.setCreatorId(curUser.getUserId()); file.setDelFlag(FileAttach.FLAG_NOT_DEL); FileAttach newFile = new FileAttach(); if(file.getTotalBytes()>0) { //将文件信息存入数据库 newFile = fileAttachService.save(file); } //组建返回文件信息的json字符串 sb1.append(newFile.getFileId()+","); } } if(sb2.toString().equals("")){ String str = sb1.substring(0, sb1.length()-1); if(str!=null&&(!str.equals("null"))&&str.length()>0) { sb.append(str); } sb.append("]}"); }else{ System.out.println("=======出错========"); sb = new StringBuffer("{'success':false,'message':'"+sb2.toString()+"'}"); } resp.setContentType("text/html;charset=UTF-8"); PrintWriter writer = resp.getWriter(); writer.println(sb.toString()); } catch(Exception e) { resp.getWriter().write("{'success':false,'message':'error..."+e.getMessage()+"'}"); } } @Override public void init(ServletConfig config) throws ServletException { super.init(config); this.servletConfig=config; } public void init() throws ServletException { //初始化上传的路径及临时文件路径 uploadPath=getServletContext().getRealPath("/attachFiles/"); File uploadPathFile=new File(uploadPath); if(!uploadPathFile.exists()){ uploadPathFile.mkdirs(); } tempPath=uploadPath+"/temp"; File tempPathFile=new File(tempPath); if(!tempPathFile.exists()){ tempPathFile.mkdirs(); } } /*------------------------------------------------------------ 保存文档到服务器磁盘,返回值true,保存成功,返回值为false时,保存失败。 --------------------------------------------------------------*/ @SuppressWarnings("unused") public boolean saveFileToDisk(String officefileNameDisk) { File officeFileUpload = null; FileItem officeFileItem =null ; boolean result=true ; try { if(!"".equalsIgnoreCase(officefileNameDisk)&&officeFileItem!=null) { officeFileUpload = new File(uploadPath+officefileNameDisk); officeFileItem.write(officeFileUpload); } }catch(FileNotFoundException e){ }catch(Exception e){ e.printStackTrace(); result=false; } return result; } private String getStrFileSize(double size){ DecimalFormat df=new DecimalFormat("0.00"); if(size>1024*1024){ double ss=size/(1024*1024); return df.format(ss)+" M"; }else if(size>1024){ double ss=size/1024; return df.format(ss)+" KB"; }else{ return size+" bytes"; } } }
标签:String,new,SSH,file,fi,文件类型,null,上传 From: https://www.cnblogs.com/dirgo/p/17839189.html