漏洞解决方案-图形验证码

漏洞解决方案-图形验证码

前置知识

图形验证码是验证码的一种。验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computers and Humans Apart”(全自动区分计算机和人类的图灵测试)的缩写,是一种区分用户是计算机还是人的公共全自动程序。可以防止:恶意破解密码、刷票、论坛灌水等,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解、枚举、重放等方式进行不断的操作或枚举猜解。

  • 威胁描述:
    图形验证码作为前端防止暴力破解、枚举、重放的手段,存在以下威胁:
    1、自动化工具获取或识别。
    (1)图形验证码文本内容直接在response中返回,可直接使用工具读取;
    (2)图形验证码未采取图片底纹干扰、颜色变换、设置非连续性及旋转图片字体、变异字体显示样式等有效方式,可使用自动识别工具识别图片上的信息。
    2、无效的图形验证码。图形验证码在成功使用一次后,服务端未立即重置,可重复使用,导致图形验证码失效。
  • 涉及功能点:
    登录、交易、短信验证码请求等。

修复方案

  • 图形验证码应在服务端随机生成,在服务端验证,客户端源文件、服务器response响应中不应包含图形验证码文本内容
  • 图形验证码应采取图片底纹干扰、颜色变换、设置非连续性及旋转图片字体、变异字体显示样式等有效方式,防止自动识别工具识别图片上的信息。
  • 图形验证码在成功使用一次后,服务端应立即重置,防止重复使用。

代码参考

  • 安全开发实例:
    (1)生成图形验证码参考代码。
    代码功能:随机生成4位的图形验证码,包括字大小写字母、数字;对图形验证码进行底纹干扰、 文本位置调整、文本颜色变换、旋转图片字体。
Public void code(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
	resp.setContentType("image/jpeg");//设置响应内容的类型为jpeg的图片
	int width=64;
	int height=40;
	BufferedImage bImg=new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
	Graphics g=bImg.getGraphics();
	//背景
	g.setColor(Color.white);
	g.fillRect(0, 0, width, height);
	//字体颜色
	g.setFont(new Font("aa", Font.BOLD,18));
	// 验证码中所使用到的字符
	char[] codeChar = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".toCharArray();
	String captcha = ""; // 存放生成的验证码
	Random r=new Random();
	for(int i=0; i<4; i++) { //设置长度单位,随机取的个数
		int t=r.nextInt(codeChar.length);// 循环将每个验证码字符绘制到图片上
		int y=10+r.nextInt(20);//上下位置:10~30
		Color c=new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255));
		g.setColor(c);
		g.drawString(codeChar[t]+"", i*16, y);
		captcha += codeChar[t];
	}
	//画干扰线
	for(int i=1; i<8; i++) {
		Color c=new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255));
		g.setColor(c);
		g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height));
	}
	// 将生成的验证码code放入sessoin中
	req.getSession().setAttribute("code", captcha);
	//把图形刷到bImg对象中
	g.dispose();//相当于IO中的close()方法带自动flush();
	ImageIO.write(bImg,"JPEG", resp.getOutputStream());//通过resp获取req的outputStream对象,发向客户端的socket的封装,即写到客户端
} 

效果如下:
在这里插入图片描述
(2)验证图形验证码参考代码:
代码功能:验证图形验证码内容,验证成功后,重置图形验证码。

protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
       // 获取存放在session中的验证码
       String code = (String) req.getSession().getAttribute("code");
       // 获取页面提交的验证码
       String inputCode = req.getParameter("code");
       if(code.toLowerCase().equals(inputCode.toLowerCase())) { // 验证码转换为小写,验证图片验证码内容
              new ImageServlect().code(req,resp);   //验证成功后重新调用生成验证码方法,将验证过的验证码重置
              checkCode();  //此处根据实际业务,做相应的操作,如验证账号密码、发送短信等
       } else { // 验证失败
        req.getRequestDispatcher("/fail.jsp").forward(req, resp);
       }
}

猜你喜欢

转载自blog.csdn.net/baidu_35488871/article/details/107911537