Java对上传的图片进行格式校验以及安全性校验
文章目录
- 前言
- 判断上传的是否是图片
- 通过后缀名进行判断
- 通过文件头
- 通过ImageIO判断
- 图片文件的安全检查处理
- 给图片加水印
前言
在web开发中,肯定会有一些图片上传的功能,如果仅仅是通过页面端进行控制是远远不够的,完全可以直接调用后台的接口,将一些病毒文件上传到服务器,如果不进行校验,后果不堪设想!
判断上传的是否是图片
通过后缀名进行判断
这层校验应该说是最基本的校验了,看下文件的后缀名是否符合要求的格式。
String fileType= "";
int i = fileName.lastIndexOf('.');
if (i > 0) {fileType= fileName.substring(i+1);
}
//...
if("jpg".equals(fileType) || "png".equals(fileType) ....){//your code
}
这种非常的不靠谱,完全可以修改文件的后缀名绕过检验。
通过文件头
根据文件的前面几个字节,即常说的魔术数字进行判断,不同文件类型的开头几个字节
// 获得文件头部字符串public static String bytesToHexString(byte[] src) {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);if (hv.length() < 2) {stringBuilder.append(0);}stringBuilder.append(hv);}return stringBuilder.toString();}
不同文件的头魔术数字
private static void getAllFileType() { FILE_TYPE_MAP.put("jpg", "FFD8FF"); //JPEG FILE_TYPE_MAP.put("png", "89504E47"); //PNG FILE_TYPE_MAP.put("gif", "47494638"); //GIF FILE_TYPE_MAP.put("tif", "49492A00"); //TIFF FILE_TYPE_MAP.put("bmp", "424D"); //Windows Bitmap FILE_TYPE_MAP.put("dwg", "41433130"); //CAD FILE_TYPE_MAP.put("html", "68746D6C3E"); //HTML FILE_TYPE_MAP.put("rtf", "7B5C727466"); //Rich Text Format FILE_TYPE_MAP.put("xml", "3C3F786D6C"); FILE_TYPE_MAP.put("zip", "504B0304"); FILE_TYPE_MAP.put("rar", "52617221"); FILE_TYPE_MAP.put("psd", "38425053"); //PhotoShop FILE_TYPE_MAP.put("eml", "44656C69766572792D646174653A"); //Email [thorough only] FILE_TYPE_MAP.put("dbx", "CFAD12FEC5FD746F"); //Outlook Express FILE_TYPE_MAP.put("pst", "2142444E"); //Outlook FILE_TYPE_MAP.put("office", "D0CF11E0"); //office类型,包括doc、xls和ppt FILE_TYPE_MAP.put("mdb", "000100005374616E64617264204A"); //MS Access FILE_TYPE_MAP.put("wpd", "FF575043"); //WordPerfect FILE_TYPE_MAP.put("eps", "252150532D41646F6265"); FILE_TYPE_MAP.put("ps", "252150532D41646F6265"); FILE_TYPE_MAP.put("pdf", "255044462D312E"); //Adobe Acrobat FILE_TYPE_MAP.put("qdf", "AC9EBD8F"); //Quicken FILE_TYPE_MAP.put("pwl", "E3828596"); //Windows Password FILE_TYPE_MAP.put("wav", "57415645"); //Wave FILE_TYPE_MAP.put("avi", "41564920"); FILE_TYPE_MAP.put("ram", "2E7261FD"); //Real Audio FILE_TYPE_MAP.put("rm", "2E524D46"); //Real Media FILE_TYPE_MAP.put("mpg", "000001BA"); // FILE_TYPE_MAP.put("mov", "6D6F6F76"); //Quicktime FILE_TYPE_MAP.put("asf", "3026B2758E66CF11"); //Windows Media FILE_TYPE_MAP.put("mid", "4D546864"); //MIDI (mid) }
此时有人把一个可执行的PHP文件的扩展名修改为PNG,然后再在前面补上”89 50″两个字节,就又绕开了这种验证方式,这种也是不靠谱的!
通过ImageIO判断
- 通过ImageReader来解码这个file并返回一个BufferedImage对象,如果找不到合适的ImageReader则会返回null,我们可以认为这不是图片文件。
- 另外如果能够正常的获取到一张图片的宽高属性,那肯定这是一张图片,因为非图片文件我们是获取不到它的宽高属性的。
/*** 通过读取文件并获取其width及height的方式,来判断判断当前文件是否图片,这是一种非常简单的方式。* @param imageFile* @return*/public static boolean isImage(File imageFile) {if (!imageFile.exists()) {return false;}Image img = null;try {img = ImageIO.read(imageFile);if (img == null || img.getWidth(null) <= 0 || img.getHeight(null) <= 0) {return false;}return true;} catch (Exception e) {return false;} finally {img = null;}}
这种方式较安全!
图片文件的安全检查处理
通过上面的方法,确认上传的文件是图片了,但是如果在可以正常打开的图片里面加入非法代码或者病毒,那就非常危险了。那么怎么可以预防这种情况,既能够正常打开,又能获取图片的宽高等属性,可以对图片进行重写,新生成的图片不会有这种恶意代码了。
给图片加水印
/*** 给图片添加水印、可设置水印图片旋转角度* @param iconPath 水印图片路径* @param srcImgPath 源图片路径* @param targerPath 目标图片路径* @param degree 水印图片旋转角度* @param width 宽度(与左相比)* @param height 高度(与顶相比)* @param clarity 透明度(小于1的数)越接近0越透明*/public static void waterMarkImageByIcon(String iconPath, String srcImgPath,String targerPath, Integer degree, Integer width, Integer height,float clarity) {OutputStream os = null;try {Image srcImg = ImageIO.read(new File(srcImgPath));System.out.println("width:" + srcImg.getWidth(null));System.out.println("height:" + srcImg.getHeight(null));BufferedImage buffImg = new BufferedImage(srcImg.getWidth(null),srcImg.getHeight(null), BufferedImage.TYPE_INT_RGB);// 得到画笔对象Graphics2D g = buffImg.createGraphics();// 设置对线段的锯齿状边缘处理g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);g.drawImage(srcImg.getScaledInstance(srcImg.getWidth(null),srcImg.getHeight(null), Image.SCALE_SMOOTH), 0, 0,null);if (null != degree) {// 设置水印旋转g.rotate(Math.toRadians(degree),(double) buffImg.getWidth() / 2,(double) buffImg.getHeight() / 2);}// 水印图象的路径 水印一般为gif或者png的,这样可设置透明度ImageIcon imgIcon = new ImageIcon(iconPath);// 得到Image对象。Image img = imgIcon.getImage();float alpha = clarity; // 透明度g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,alpha));// 表示水印图片的位置g.drawImage(img, width, height, null);g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));g.dispose();os = new FileOutputStream(targerPath);// 生成图片ImageIO.write(buffImg, "JPG", os);System.out.println("添加水印图片完成!");} catch (Exception e) {e.printStackTrace();} finally {try {if (null != os)os.close();} catch (Exception e) {e.printStackTrace();}}}/*** 给图片添加水印、可设置水印图片旋转角度* @param logoText 水印文字* @param srcImgPath 源图片路径* @param targerPath 目标图片路径* @param degree 水印图片旋转角度* @param width 宽度(与左相比)* @param height 高度(与顶相比)* @param clarity 透明度(小于1的数)越接近0越透明*/public static void waterMarkByText(String logoText, String srcImgPath,String targerPath, Integer degree, Integer width, Integer height,Float clarity) {// 主图片的路径InputStream is = null;OutputStream os = null;try {Image srcImg = ImageIO.read(new File(srcImgPath));BufferedImage buffImg = new BufferedImage(srcImg.getWidth(null),srcImg.getHeight(null), BufferedImage.TYPE_INT_RGB);// 得到画笔对象// Graphics g= buffImg.getGraphics();Graphics2D g = buffImg.createGraphics();// 设置对线段的锯齿状边缘处理g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);g.drawImage(srcImg.getScaledInstance(srcImg.getWidth(null),srcImg.getHeight(null), Image.SCALE_SMOOTH), 0, 0,null);if (null != degree) {// 设置水印旋转g.rotate(Math.toRadians(degree),(double) buffImg.getWidth() / 2,(double) buffImg.getHeight() / 2);}// 设置颜色g.setColor(Color.red);// 设置 Fontg.setFont(new Font("宋体", Font.BOLD, 30));float alpha = clarity;g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,alpha));// 第一参数->设置的内容,后面两个参数->文字在图片上的坐标位置(x,y) .g.drawString(logoText, width, height);g.dispose();os = new FileOutputStream(targerPath);// 生成图片ImageIO.write(buffImg, "JPG", os);System.out.println("添加水印文字完成!");} catch (Exception e) {e.printStackTrace();} finally {try {if (null != is)is.close();} catch (Exception e) {e.printStackTrace();}try {if (null != os)os.close();} catch (Exception e) {e.printStackTrace();}}}public static void main(String[] args) throws IOException {waterMarkImageByIcon("d:/shuiyin.png", imagePath, "d:/result.png", 10, 100, 100, 0F);waterMarkByText("logo", imagePath, "d:/result1.png", 3, 100, 100, 0F);}
上面加水印,你可以将透明度调为0,乍一看跟原图一样,其实不是上面的那张原图了。
效果展示
原图:
加水印图片(水印透明度0.5):
加水印文字(水印透明度0.5):
Java对上传的图片进行格式校验以及安全性校验相关推荐
- java 图片格式校验_(转载)Java对上传的图片进行格式校验以及安全性校验
文章目录 前言 判断上传的是否是图片 通过后缀名进行判断 通过文件头 通过ImageIO判断 图片文件的安全检查处理 给图片加水印 前言 在web开发中,肯定会有一些图片上传的功能,如果仅仅是通过页面 ...
- java 上传的图片大小为0_JAVA技术:上传图片的缩放处理
图片上传到后,会根据情况将图片缩小成一个图标,我们可以利用java强大的图形处理功能,对上传的图片进行缩放处理. 下面的程序使用jdk1.4中最新的ImageIO对图片进行读写.使用AffineTra ...
- JAVA上传文件图片到服务器保存
这里我记录一个比较简单方便操作的JAVA上传文件图片到服务器并且保存! 首先是页面 html的 我这是提交一个文件和类型 <div style="border: 1px solid ...
- java上传文件图片到服务器保存,Java上传文件图片到服务器的方法
这里我记录一个比较简单方便操作的java上传文件图片到服务器并且保存,具体内容如下 首先是页面html的 我这是提交一个文件和类型 我是添加一张临时图片得到微信的media_id保存数据库! en ...
- Java 对上传文件进行魔数校验
魔数这个词在不同领域代表不同的含义.在计算机领域,魔数有两个含义,一指用来判断文件类型的魔数(magic number):二指程序代码中的魔数,也称魔法值. 不是所有文件都有文件头的.一个.txt类型 ...
- Java判断上传的文件是否是图片,如果是就对上传的图片进行压缩
1.导入依赖 <!-- 图片缩略图 --> <dependency> <groupId>net.coobir ...
- java 微信开发图片发送,微信开发?Java上传Base64图片
class="java">import org.apache.commons.codec.binary.Base64; import org.apache.log4j.Log ...
- java上传png_java图片上传
1 /***2 * 上传证明材料3 *@paramfiles4 *@paramrequest5 *@return 6 */ 7 @RequestMapping(value = "/bitch ...
- java 上传远程图片,java上传图片到另一台服务器上,怎么解决
Java codepublic String upload(String dir, FormFile formFile) throws Exception { Date date = new Date ...
- Java 利用Graphics2D 合并图片(png格式可设置透明)
利用Graphics2D 合并图片 效果如下: 图一图二合并成图三 tip: 需要上图的效果 frontgroud需要为png格式 附上代码: import javax.imageio.ImageI ...
最新文章
- linux telnet远程登录工具,Linux 远程登录(telnet ssh)
- 一个Java递归删除目录的方法
- python去噪算法
- Rime在linux下面的安装-还没写完
- python 硬件自动化测试_村长告诉你:Python实现性能自动化测试竟然如此简单
- 并发编程(二)线程并发工具类
- linux用于开发qt java_Linux下Qt程序的打包发布
- 将Unix时间戳字符串转换为可读日期
- 推荐!手把手教你使用Git(转)
- 天题系列:Substring with Concatenation of All Words
- 切割钢板计算机软件,板材切割优化软件钢板开料套料软件 V1.0 官方版
- java程序设计大赛acm_转载(ACM国际大学生程序设计大赛)
- 什么是https安全证书
- python脚本之对文件进行哈希校验
- 听歌识曲C++程序说明
- 设计模式 - 创建型模式_工厂方法模式
- python dataframe是什么_什么是Pandas的DataFrame?
- Flink 计算 TopN
- 操作系统总结(二)系统调用及系统结构
- 勒索软件攻击:如何使用加密来保护您的数据