一次性验证码

来源:互联网 发布:国外网络音乐版权 编辑:程序博客网 时间:2024/05/16 00:41

转自:http://my.oschina.net/hongdengyan/blog/181998

一次性验证码的作用

防止暴力破解。

二、实现 

1.创建jsp页面,在页面中添加一个img标签,指向一个生成图片的servlet,设置img宽度和高度 

2.创建生成图形验证码的Servlet 

该Servlet根据生成的随机码产生一个图形流并返回,可以将该图形做一些混淆操作,同时将该随机码保存到当前用户session中。 

3.验证码比对 

将用户提交上来的验证码和保存到当前用户session中的随机码进行比对。 

4.刷新验证码。

使用javascript刷新验证码。 

三、示例代码

login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPEhtml PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<metahttp-equiv="Content-Type"content="text/html; charset=UTF-8">
<title>Insert title here</title>
<scripttype="text/javascript">
    function change() {
        var contextPath = document.getElementById("contextPath").value;
        document.getElementById("randomCode").src = contextPath+"/randomCode?"+Math.random();
    }
</script>
</head>
<body>
<inputtype="hidden"id="contextPath"value="<%=request.getContextPath() %>">
<formmethod="post"action="<%=request.getContextPath() %>/login">
<table>
    <tr>
        <td>姓名:</td>
        <td><inputtype="text"name="username"/></td>
    </tr>
    <tr>
        <td>密码:</td>
        <td><inputtype="password"name="password"/></td>
    </tr>
    <tr>
        <td>验证码:</td>
        <td><inputtype="text"name="randomCode"/></td>
    </tr>
    <tr>
        <td></td>
        <tdcolspan="2"><imgalt=""src="<%=request.getContextPath() %>/randomCode" width="100"
            height="35" id="randomCode" title="看不清楚,点击换一张" onclick="change()" /></td>
    </tr>
    <tr>
        <tdcolspan="2"><inputtype="submit"value="登陆"/></td>
    </tr>
</table>
</form>
</body>
</html>
RandomCodeServlet.java

packagecn.heimar.randomCode;
 
importjava.awt.Color;
importjava.awt.Font;
importjava.awt.Graphics;
importjava.awt.image.BufferedImage;
importjava.io.IOException;
importjava.util.Random;
 
importjavax.imageio.ImageIO;
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importjavax.servlet.http.HttpSession;
 
publicclass RandomCodeServlet extendsHttpServlet {
 
    @Override
    protectedvoid service(HttpServletRequest req, HttpServletResponse resp)
            throwsServletException, IOException {
 
        intrandomNumber = 5;
        // 图片宽度
        intwidth = 100;
        // 图片高度
        intheight = 35;
        // 创建随机码
        char[] ranlist = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
                .toCharArray();
        StringBuilder sb = newStringBuilder();
        Random randomer = newRandom();
        for(inti = 0; i < randomNumber; i++) {
            sb.append(ranlist[randomer.nextInt(ranlist.length)]);
        }
        // 保存到session中
        HttpSession session = req.getSession();
        session.setAttribute("RANDOM_IN_SESSION", sb.toString());
 
        // 画画
        // 创建一个图片对象
        BufferedImage image = newBufferedImage(width, height,
                BufferedImage.TYPE_INT_BGR);
        // 得到图片对象对应的绘画缓存,绘画都在Graphics对象上
        Graphics g = image.getGraphics();
 
        // 绘制背景
        g.setColor(Color.WHITE);
        // 填充矩形
        g.fillRect(0,0, width, height);
        // 绘制边框
        g.setColor(Color.BLACK);
        g.drawRect(0,0, width - 1, height - 1);
        // 绘制文字
        g.setColor(Color.GRAY);
        g.setFont(newFont("宋体", Font.ITALIC, 24));
        g.drawString(sb.toString(),13, height - 9);
 
        //绘制干扰点
        for(inti = 0; i < 300; i++) {
            g.fillRect(randomer.nextInt(width - 1),
                    randomer.nextInt(height - 1),1,1);
        }
        // 关闭绘画资源
        g.dispose();
 
        //清除图片缓存:IE7  firefox验证码没有反应问题
        //设定网页的到期时间,一旦过期则必须到服务器上重新调用
        resp.setDateHeader("Expires",-1);
        //Cache-Control指定请求和响应遵循的缓存机制   no-cache指示请求或响应消息不能缓存
        resp.setHeader("Cache-Control","no-cache");
        //是用于设定禁止浏览器从本地机的缓存中调阅页面内容,设定后一旦离开网页就无法从Cache中再调出
        resp.setHeader("Pragma","no-cache");
         
        // 输出
        ImageIO.write(image,"JPG", resp.getOutputStream());
    }
 
}
LoginServlet.java

packagecn.heimar.randomCode;
 
importjava.io.IOException;
 
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importjavax.servlet.http.HttpSession;
 
publicclass LoginServlet extendsHttpServlet {
 
    @Override
    protectedvoid service(HttpServletRequest req, HttpServletResponse resp)
            throwsServletException, IOException {
        HttpSession session = req.getSession();
        String randomForm = req.getParameter("randomCode");
        String username = req.getParameter("username");
        String randomInSession = (String) session
                .getAttribute("RANDOM_IN_SESSION");
        if(randomForm.equals(randomInSession)) {
            req.getRequestDispatcher("/WEB-INF/success.jsp").forward(req, resp);
            session.removeAttribute("RANDOM_IN_SESSION");
        }else{
            resp.sendRedirect(req.getContextPath()+"/login.jsp");
        }
    }
 
}

四、个别浏览器验证码不能刷新的问题 

1.问题说明 

在IE6下面图片刷新正常,但IE7和Firefox浏览器刷新不成功。  

2.原因分析 

如果新的图片跟旧的图片地址不一样,图片刷新会正常。但是验证码功能访问图片的地址是一样的。因此浏览器自动读取的是缓存中的内容。  

3.解决方法 

3.1利用随机数 

将js中路径后加上Math.random();  
?
1
2
3
4
functionchange() {
    varcontextPath = document.getElementById("contextPath").value;
    document.getElementById("randomCode").src = contextPath+"/randomCode?"+Math.random();
}

3.2利用时间戳 

?
1
2
3
4
functionchange() {
    varcontextPath = document.getElementById("contextPath").value;
    <span></span>document.getElementById("randomCode").src = contextPath+"/randomCode?"+Date.parse(newDate());
}

0 0
原创粉丝点击