首页 > 代码库 > JavaWeb——图片验证码技术

JavaWeb——图片验证码技术

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6134649.html

    在常见的登录功能实现中,单靠账户、密码登录很容易遭受恶意攻击,有些人可以通过写一些脚本自动输入账户密码(当然,是瞎蒙的)频繁登录从而占用服务器的处理资源。这时候,此时,就可以通过验证码来达到拦截“非人类”发出请求。

    验证码:全自动区分计算机和人类的图灵测试的缩写,是一种区分用户是计算机的公共全自动程序,这个问题可以由计算机生成并评判,但是必须只有人类才能解答.可以防止恶意破解密码、刷票、论坛灌水、有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登录。

    实现原理:在服务器的servlet中随机生成一个验证码,一般为四位数字、字母,然后把该验证码保存到session作为一个Attribute,然后通过Java的绘图类以图片的形式把该验证码写到浏览器,并设置给Img标签以图片的形式显示出来。最后,在用户提交数据的时候,在服务器端将用户提交的验证码和session中保存的验证码属性值进行比较,并发回验证结果。(如:验证成功则跳转、不成功则发回错误码重新输入)

    代码实现:

    前端:用一个img标签显示验证码图片,一个输入框接收用户输入的验证码。

   

<script>
    function show(o){     
    //单击图片,重新获得验证码。random的作用是用来修改img图片的来源的,如果没有随机数后缀,则说明没有修改src,则img的内容不会重新获取,则没有实现刷新
    o.src = "http://www.mamicode.com/checkCode.jsp?"+Math.random();
    }
</script>
    <form method="post" action="reg_do.jsp">
        请输入验证码:
        <input type="text" name="randomCode_Client" />
        <br/><br/>
        <img src="http://www.mamicode.com/checkCode.jsp" onclick="show(this)" />
        <br/><br/>        
    </form>

    后台:处理登录请求,校对验证码

    //得到客户端传入的验证码参数
    String randomCode_client=(String)request.getParameter("randomCode_Client");
    //得到session上的验证码
    String randomCode_server=(String)session.getAttribute("randomCode");
    
    if(!randomCode_client.equals(randomCode_server)){
        //验证码错误做出的响应
    }else{
        //验证码正确做出的响应
    }    

    后台:生成验证码图片并设置到session中,并把图片输出到浏览器显示

   

int width = 62, height = 22;//定义验证码图片的大小
BufferedImage buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);//在内存中创建图象
Graphics2D g = buffImg.createGraphics();//为内存中要创建的图像生成画布,用于“作画”

//画一个白色矩形,作为验证码背景 
g.setColor(Color.WHITE);
g.fillRect(0, 0, width, height);
//画一个黑色矩形边框
g.setColor(Color.BLACK);
g.drawRect(0, 0, width - 1, height - 1);

//画40条灰色的随机干扰线
g.setColor(Color.GRAY);
Random random = new Random();        //设置随机种子        
for (int i = 0; i < 40; i++) {        //设置40条干扰线
    int x1 = random.nextInt(width);
    int y1 = random.nextInt(height);
    int x2 = random.nextInt(10);//返回0到10之间一个随机数
    int y2 = random.nextInt(10);            
    g.drawLine(x1, y1, x1 + x2, y1 + y2);
}

//创建字体
Font font = new Font("Times New Roman", Font.PLAIN, 18);
g.setFont(font);

int length = 4;                        //设置默认生成4个长度的验证码
StringBuffer randomCode = new StringBuffer();        
for (int i = 0; i < length; i++) {    //取得4位数的随机字符串
    String strRand = String.valueOf(random.nextInt(10));//返回一个伪随机数,它是取自此随机数生成器序列的、在 0(包括)和指定值(不包括)之间均匀分布的 int 值
    int red = random.nextInt(255);
    int green = random.nextInt(255);
    int blue = random.nextInt(255);
    g.setColor(new Color(red, green, blue));   //获得一个随机红蓝绿的配合颜色         
    g.drawString(strRand, 13 * i + 6, 16);//把该数字用画笔在画布画出,并指定数字的坐标
    randomCode.append(strRand);//把该数字加到缓存字符串中。用于等会生成验证码字符串set到session中用于校对
}

buffImg.flush();//清除缓冲的图片
g.dispose();//释放资源


session.setAttribute("randomCode", randomCode.toString());//把验证码set为属性

//设置页面不缓存
response.setContentType("image/jpeg");
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);

ServletOutputStream outputStream = response.getOutputStream();
ImageIO.write(buffImg, "jpeg", outputStream);//使用支持jpeg格式的 ImageWriter 将一个图像写入 OutputStream。而在客户端的img标签通过src来从中提取出jpeg图片
outputStream.close();


/*
这两句代码用于解决报错:java.lang.IllegalStateException: getOutputStream() has already been called
由于jsp container在处理完成请求后会调用releasePageContet方法释放所用的PageContext object,
并且同时调用getWriter方法,由于getWriter方法与在jsp页面中使用流相关的getOutputStream方法冲突,
所以会造成这种异常
*/ out.clear(); out
= pageContext.pushBody();

JavaWeb——图片验证码技术