其实实现代码的逻辑很是简单,真的超级超级简单。java
一、在登陆页面上login.jsp将验证码图片使用标签<img src="xxx">将绘制验证码图片的url给它浏览器
二、在服务器端就两个servlet,一个就是用来绘制验证码图片的VerifyCodeServlet,另外一个就是登陆时验证验证码是否点写正确或是否重复提交的LoginServlet缓存
三、在VerifyCodeServlet中,将验证码的四个字母存入session中,而后在LoginServlet中,将请求中提交过来的验证码与session中的进行对比,若是正确,则验证成功,而且将session中的验证码删除,为何要删除?保证session中的数据只能被用一次,防止重复提交数据,若是不正确,就使用request,将错误信息保存,而后请求转发到登陆页面显示错误信息,若是发现session中的数据为null,说明重复提交了数据,也将错误信息用一样的方法返回到登陆页面。服务器
难点就在于:VerifyCodeServlet的代码实现.对绘图的代码不是很熟悉。session
login.jspapp
<body> <% String msg = (String)request.getAttribute("msg"); if(msg != null){ out.print(msg); } %> <form action="/test01/LoginServlet" method="post"> 用户名:<input type="text" name="username" /> <br/> 验证码:<input type="text" name="verifyCode" size="5" /> <img src="/test01/VerifyCodeServlet" /> <br/> <input type="submit" value="提交"/> </form> </body>
VerifyCodeServlet.javadom
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //声明验证码 int width = 60; int height = 30; String data = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789abcdefghijklmnpqrstuvwxyz"; //随机字符字典,其中0,o,1,I 等难辨别的字符最好不要 Random random = new Random();//随机类 //1 建立图片数据缓存区域(核心类) BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);//建立一个彩色的图片 //2 得到画板(图片,ps图层),绘画对象。 Graphics g = image.getGraphics(); //3 选择颜色,画矩形3,4步是画一个有内外边框的效果 g.setColor(Color.BLACK); g.fillRect(0, 0, width, height); //4白色矩形 g.setColor(Color.WHITE); g.fillRect(1, 1, width-2, height-2); /**1 提供缓存区域,为了存放4个随机字符,以便存入session */ StringBuilder builder = new StringBuilder(); //5 随机生成4个字符 //设置字体颜色 g.setFont(new Font("宋体", Font.BOLD&Font.ITALIC, 20)); for(int i = 0 ; i < 4 ;i ++){ //随机颜色 g.setColor(new Color(random.nextInt(255),random.nextInt(255), random.nextInt(255))); //随机字符 int index = random.nextInt(data.length()); String str = data.substring(index, index + 1); /**2 缓存*/ builder.append(str); //写入 g.drawString(str, (width / 6) * (i + 1) , 20); } //给图中绘制噪音点,让图片不那么好辨别 for(int j=0,n=random.nextInt(100);j<n;j++){ g.setColor(Color.RED); g.fillRect(random.nextInt(width),random.nextInt(height),1,1);//随机噪音点 } /**3 得到随机数据,并保存session*/ String tempStr = builder.toString(); request.getSession().setAttribute("sessionCacheData",tempStr); //.. 生成图片发送到浏览器 --至关于下载 ImageIO.write(image, "jpg", response.getOutputStream()); }
LoginServlet.javajsp
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1 得到用户输入的验证码 String verifyCode = request.getParameter("verifyCode"); //2 得到服务器session 存放数据 ,若是没有返回null String sessionCacheData = (String) request.getSession().getAttribute("sessionCacheData"); // *将服务器缓存session数据移除 request.getSession().removeAttribute("sessionCacheData"); // ** 判断服务器是否存在 if(sessionCacheData == null){ request.setAttribute("msg", "请不要重复提交"); request.getRequestDispatcher("/login.jsp").forward(request, response); return; } //3 比较 if(! sessionCacheData.equalsIgnoreCase(verifyCode)){ //用户输入错误 // * 存放request做用域 request.setAttribute("msg", "验证码输入错误"); // * 请求转发 request.getRequestDispatcher("/login.jsp").forward(request, response); return; } //...... 登陆操做 } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
效果图:ide
验证码错误时:post
注意:
若是要拷贝代码的话,须要改就应该就是那几处url,你的确定跟个人不同,而且有些人设置的servlet的访问路径也不同,因此拷贝的话只须要拷贝关键代码便可。