09.基于Tomcat的用户验证码登陆实现
通常在实际的项目开发中实现登录的时候需要提供验证码功能,主要目的是为了防止鸡血代码暴力破解密码,验证码原理是在服务器端生成验证码信息并且保存在session对象中,再将这个验证码的副本以流的方式发送一份到浏览器显示到页面,用户再将这个验证码填写到表单提交到服务器端和保存在session中的验证码做对比。如果相同,则再继续进行密码和用户名的验证,如果不相同则提示验证码不正确(可以通过一些技术实现识别图片中的文字,为了解决这样的问题,可以在验证码中添加干扰线)。发展到现在很多应用使用的是手机短信验证了。
1.实现验证码RandomCode.java
package com.sxt.mvcpro.util; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Random; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; @WebServlet("/imgCode") public class RandomCode extends HttpServlet { private static final long serialVersionUID = 1L; private static int WIDTH = 102; private static int HEIGHT = 50; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); response.setContentType("image/jpeg"); ServletOutputStream sos = response.getOutputStream(); response.setHeader("Pragma", "No-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0); BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); Graphics g = image.getGraphics(); char[] rands = generateCheckCode(); drawBackground(g); drawRands(g, rands); g.dispose(); ByteArrayOutputStream bos = new ByteArrayOutputStream(); ImageIO.write(image, "JPEG", bos); byte[] buf = bos.toByteArray(); response.setContentLength(buf.length); sos.write(buf); bos.close(); sos.close(); session.setAttribute("rand", new String(rands)); } private void drawBackground(Graphics g) { g.setColor(new Color(0xDCDCDC)); g.fillRect(0, 0, WIDTH, HEIGHT); for (int i = 0; i < 120; i++) { int x = (int) (Math.random() * WIDTH); int y = (int) (Math.random() * HEIGHT); int red = (int) (Math.random() * 255); int green = (int) (Math.random() * 255); int blue = (int) (Math.random() * 255); g.setColor(new Color(red, green, blue)); g.drawOval(x, y, 1, 0); } } private void drawRands(Graphics g, char[] rands) { // g.setColor(Color.BLUE); Random random = new Random(); int red = random.nextInt(110); int green = random.nextInt(50); int blue = random.nextInt(50); g.setColor(new Color(red, green, blue)); g.setFont(new Font(null, Font.ITALIC | Font.BOLD, 30)); g.drawString("" + rands[0], 5, 35); g.drawString("" + rands[1], 25, 34); g.drawString("" + rands[2], 45, 36); g.drawString("" + rands[3], 65, 33); } private char[] generateCheckCode() { String chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; char[] rands = new char[4]; for (int i = 0; i < 4; i++) { int rand = (int) (Math.random() * 36); rands[i] = chars.charAt(rand); } return rands; } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
2.在服务器端使用验证码(EmpServlet.java)
package com.sxt.mvcpro.controller; import java.io.IOException; import java.util.List; import java.util.concurrent.TimeUnit; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jdt.internal.compiler.ast.ThisReference; import com.sxt.mvcpro.factory.ServiceFactory; import com.sxt.mvcpro.service.IEmpService; import com.sxt.mvcpro.service.impl.EmpServiceImpl; import com.sxt.mvcpro.vo.Emp; @SuppressWarnings("serial") @WebServlet(urlPatterns= {"/emp/*","/dept/*"}) public class EmpServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username = req.getParameter("username"); String pwd = req.getParameter("pwd"); String ranCode = req.getParameter("code"); // 先判断验证码是否正确 if (ranCode.equalsIgnoreCase((String) req.getSession().getAttribute("rand"))) { if ("smith".equals(username)&&"1234".equals(pwd)) { req.getSession().setAttribute("name", username); resp.sendRedirect("/MvcPro/pages/welcome.jsp"); } else { req.setAttribute("mag", "用户名密码不正确"); req.getRequestDispatcher("/pages/login.jsp").forward(req, resp); } } else { req.setAttribute("msg", "验证码不正确"); req.getRequestDispatcher("/pages/login.jsp").forward(req, resp); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } }
3.修改表单(login.jsp)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <base href="/MvcPro/"/> <meta charset="UTF-8"> <title>Insert title here</title> <script type="text/javascript" src="js/jquery.min.js"></script> </head> <body> <span>${msg}</span> <form action="emp/login" method="post"> <fieldset> <legend>请登录</legend> 用户名:<input type="text" name="username" placehodler="输入用户名"><br><br> 密 码:<input type="password" name="pwd" placehodler="输入用户密码"><br><br> <img alt="图片不存在" src="imgCode" height="25px"><a href="javascript:void(0)"> 看不清,换一张!</a><br><br> 验证码:<input type="text" name="code"> <br><br> <input type="submit" value="提交"> <input type="reset" value="重置"> </fieldset> </form> <script type="text/javascript"> $(function(){ $("form a").click(function(){ $("form img").attr("src","imgCode?ran="+Math.random()); }) }) </script> </body> </html>
4.结果实现
当输入的验证码错误时,会提示验证码不正确。