java 图片格式校验_(转载)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);
// 设置 Font
g.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,乍一看跟原图一样,其实不是上面的那张原图了。
效果展示
原图:
image.png
加水印图片(水印透明度0.5):
image.png
加水印文字(水印透明度0.5):
image.png
————————————————
版权声明:本文为CSDN博主「太阳守护者Sunner」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_26788593/article/details/85062168
java 图片格式校验_(转载)Java对上传的图片进行格式校验以及安全性校验相关推荐
- java数组可扩展_[转载]Java数组扩容算法及Java对它的应用
Java数组扩容的原理 1)Java数组对象的大小是固定不变的,数组对象是不可扩容的. 2)利用数组复制方法可以变通的实现数组扩容. 3)System.arraycopy()可以复制数组. 4)Arr ...
- java生成sm2证书_(转载)Java使用IText实现PDF签章
前文讲到了如何使用Adobe的PDF工具软件进行电子印章应用.在实际应用中还有一种情形就是需要将电子印章功能集成在我们开发的系统里,这里就要用到一些PDF的二次开发库了.做过相关开发的同学应该知道常用 ...
- java throw 什么意思_[转载]java中throw和throws的区别
throw是一种控制程序流程的特殊方法而已.没有相应的catch的话,可以中止当前的方法继续执行. 关键字:throws 声明方法时候,如果不声明throws的话,那么一般的Exception都要在这 ...
- java对象工厂池_[转载]Java对象池技术的原理及其实现
作者:汪永好 出处:计算机与信息技术 责任编辑: 方舟 [ 2006-11-25 07:00 ] 摘 要 :本文在分析对象池技术基本原理的基础上,给出了对象池技术的两种实现方式.还指出了使用对象池技术 ...
- java 从控制台读取_转载 java从控制台读取输入的方法
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; i ...
- java dijkstra算法代码_[转载]Java实现dijkstra算法: 地图中任意起点寻找最佳路径...
最近在复习java,下学期要用,写这个练手. 技术较粗糙,见谅. 代码里用的是这幅地图,根据实际情况更改,在addNode方法中 这个是运行结果,起点和终点在 运行wrap(String qidia ...
- java四叶玫瑰_[转载]java编程——四叶玫瑰线
package edu.hit.hd.zyl; import java.awt.*; import java.awt.event.*; import javax.swing.*; public cla ...
- java word模版填充_[转载]java向word模板中填充数据(总结)
使用过PageOffice动态生成word文档的人都知道,PageOffice可以给word文档的指定位置进行填充,这里我们所说的指定位置在PageOffice的专业术语里面有两个概念,一个叫做数据区 ...
- java office 集成开发_[转载]Java集成PageOffice在线打开编辑word文件 - Spring Boot
开发环境:JDK1.8.Eclipse.Sping Boot + Thymeleaf框架. 一. 构建Sping Boot + Thymeleaf框架的项目(不再详述): 1. 新建一个maven p ...
- java项目----教务管理系统_基于Java的教务管理系统
java项目----教务管理系统_基于Java的教务管理系统 2022-04-22 18:18·java基础 最近为客户开发了一套学校用教务管理系统,主要实现学生.课程.老师.选课等相关的信息化管理功 ...
最新文章
- 简单快速修改大量重复代码(Intellij IDEA)
- AI算法起家的今日头条为何败给了色情?一文告诉你机器学习何以搞不定鉴黄
- 【转】ASP.NET中“字母和数字混合的验证码”详解
- springMVC和Shiro框架整合使用简单示例 【转】
- Android基础之一
- 时代中坚:互联网电视迎来极致时代
- linux设置密码过期时间
- pod出现include of non-modular header inside framework module 错误
- BLE蓝牙核心数据库结构解析
- ***快速理解Docker - 容器级虚拟化解决方案
- PHP的$_SERVER['HTTP_HOST']获取服务器地址功能详解
- [UE4]Uniform Grid Panel
- Setinterl全面介绍
- 免费PR转场下载 PR形状过渡视频转场MOGRT
- mongodb查询某个字段数据
- 计算机科学与技术的职业资格,软件水平考试是专业技术资格还是职业资格
- Android帧动画分析
- VTK:二次六面体用法实战
- 主轴承盖螺栓拧紧机PLC控制程序
- MFC几种给对话框添加背景图的方法