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对上传的图片进行格式校验以及安全性校验的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CTF-数据分析(二)
- 下一篇: 仿宋小二在html中怎么设置,CSS 网