`

上传文件校验

    博客分类:
  • java
阅读更多

为了防止一些用户将一些病毒文件上传到服务器,我们一般需要对上传的文件做合法性校验, 当时有时候简单的后缀和contentType校验任然还有风险,下面我们一起来讨论一下上传的文件需要做哪些合法性校验。

 

1、文件后缀校验

这层校验应该说是最基本的校验了,我们不能允许用户上传一些exe、jsp、php、asp、html等可执行的文件。

 

2、contentType校验

contentType是内容类型,它会告诉浏览器用什么形式、什么编码来读取这个文件。因此文件后缀和contentType有一个对应关系,上传文件的后缀和contentType应该是对应的,如果不对应则上传信息已被篡改。后缀和contentType关系表参考tomcat下conf/web.xml中。

 

3、上传图片校验

如果需要上传的文件是图片,必须对上传的文件是否是一个图片进行检验,否则如果用户将一个html文件修改后缀为图片并上传,在显示该图片时就会执行html文件中的内容,带来跨域攻击风险。

 

图片校验方式

(1)、通过ImageIO读取文件,如果抛出异常或者读取后的对象为null,表示该文件不是图片

 

/**
	 * 通过读取文件信息判断文件是否是图片
	 * @param imageFile
	 * @return
	 */
	public static boolean checkImageFileByRead(File imageFile){
		try {
			BufferedImage image = ImageIO.read(imageFile);
			if(image == null){
				log.error("The file could not be opened , it is not an image");
				return false;
			}
		} catch (IOException e) {
			log.error(e.getMessage(), e);
			return false;
		}
		return true;
	}

 

(2)、通过ImageIO读取文件成图片流,如果抛出异常或者读取后的流对象为null,表示文件不是图片

/**
	 * 通过将文件转换为图片流方式监测文件是否为图片
	 * @param imageFile
	 * @return
	 */
	public static boolean checkImageFileByIS(File imageFile){
		try {
			ImageInputStream is = ImageIO.createImageInputStream(imageFile);
			if(is == null){
				return false;
			}
			is.close();
		} catch (IOException e) {
			log.error(e.getMessage(), e);
			return false;
		}
		return true;
	}

 

 (3)有些图片中可能会嵌入IFrame,以同样会导致跨域攻击,可以采用添加水印方式解决

/**
     * 给图片添加水印、可设置水印图片旋转角度
    * 
     * @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);
            // 得到画笔对象
           // 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);
            }
            // 水印图象的路径 水印一般为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();
            }
        }
    }

 

 

做到这几步,一般的安全问题就解决了,如果大家有更好的解决方案,欢迎一起讨论。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics