客户端向服务端请求验证码
src="服务端验证码servlet"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <img id ="captcha" onclick ="refreshCaptcha()" class ="codeImage" alt ="验证码" src ="${ctx}/checkCode" title ="点击更换验证码" /> <script > function refreshCaptcha ( ) { $("#captcha" ).attr ("src" , "/checkCode" + "?nocache=" + new Date ().getTime ()); } <script>
接收客户端验证码请求,调用CaptchaImageUtil
生成验证码图片,并将其返回给客户端。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 package servlet;import utils.CaptchaImageUtil;import javax.imageio.ImageIO;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 java.awt.image.BufferedImage;import java.io.IOException;@WebServlet(name = "CaptchaServlet", value = "/checkCode") public class CaptchaServlet extends HttpServlet { @Override protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setHeader("Pragma" , "No-cache" ); response.setHeader("Cache-Control" , "No-cache" ); response.setDateHeader("Expires" , 0 ); response.setContentType("image/jpeg" ); BufferedImage image = CaptchaImageUtil.getPicture(80 , 35 , request); ImageIO.write(image, "JPEG" , response.getOutputStream()); } @Override protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
服务端生成验证码 CaptchaImageUtil
随机生成长度为4的字符串作为验证码,使用awt绘制包含该字符串的图片,为了增加验证码的安全级别防止ORC,在绘制图片时绘制干扰线。同时将该字符串存Session。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 package utils;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;import java.awt.*;import java.awt.geom.AffineTransform;import java.awt.geom.Line2D;import java.awt.image.BufferedImage;import java.util.Random;public class CaptchaImageUtil { private static Color getRandColor (int s, int e) { Random random = new Random (); if (s > 255 ) s = 255 ; if (e > 255 ) e = 255 ; int r, g, b; r = s + random.nextInt(e - s); g = s + random.nextInt(e - s); b = s + random.nextInt(e - s); return new Color (r, g, b); } public static BufferedImage getPicture (int width, int height, HttpServletRequest request) { String CHECK_CODES = "abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789" ; BufferedImage image = new BufferedImage (width, height, BufferedImage.TYPE_INT_RGB); Graphics g = image.getGraphics(); Graphics2D g2d = (Graphics2D) g; Random random = new Random (); Font font = new Font ("幼圆" , Font.BOLD, 25 ); g.setColor(getRandColor(200 , 250 )); g.fillRect(0 , 0 , width, height); g.setFont(font); g.setColor(getRandColor(180 , 200 )); for (int i = 0 ; i < 50 ; i++) { int x = random.nextInt(width - 1 ); int y = random.nextInt(height - 1 ); int x1 = random.nextInt(6 ) + 1 ; int y1 = random.nextInt(12 ) + 1 ; BasicStroke bs = new BasicStroke (2f , BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL); Line2D line = new Line2D .Double(x, y, x + x1, y + y1); g2d.setStroke(bs); g2d.draw(line); } StringBuilder sb = new StringBuilder (); for (int i = 0 ; i < 4 ; ++i) { char charAt = CHECK_CODES.charAt(random.nextInt(CHECK_CODES.length())); String sTemp = String.valueOf(charAt); sb.append(sTemp); Color color = new Color (20 + random.nextInt(110 ), 20 + random.nextInt(110 ), random.nextInt(110 )); g.setColor(color); Graphics2D g2d_word = (Graphics2D) g; AffineTransform trans = new AffineTransform (); trans.rotate((45 ) * 3.14 / 180 , 15 * i + 8 , 7 ); float scaleSize = random.nextFloat() + 0.8f ; if (scaleSize > 1f ) scaleSize = 1f ; trans.scale(scaleSize, scaleSize); g2d_word.setTransform(trans); g.drawString(sTemp, 15 * i + 18 , 14 ); } HttpSession session = request.getSession(true ); System.out.println("验证码绘制:" + sb); session.setAttribute("captcha" , sb.toString()); g.dispose(); return image; } }
验证码验证 客户端收到验证码图片后,输入验证码随账号密码一起提交至服务端,服务端将客户端输入的验证码与Session中保存的验证码进行比对,返回结果给客户端。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 package servlet;import dao.UserDao;import entity.User;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 javax.servlet.http.HttpSession;import java.io.IOException;import java.sql.SQLException;@WebServlet(name = "LoginServlet", value = "/login") public class LoginServlet extends HttpServlet { @Override protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username" ); String password = request.getParameter("password" ); String captcha = request.getParameter("captcha" ); UserDao userDao = new UserDao (); User user = null ; try { user = userDao.login(username, password); } catch (SQLException e) { e.printStackTrace(); } HttpSession session = request.getSession(); System.out.println("服务端生成的验证码" + session.getAttribute("captcha" )); System.out.println("输入的验证码" + captcha); if (!captcha.equalsIgnoreCase((String) session.getAttribute("captcha" ))) { request.setAttribute("loginInfo" , "201" ); } else if (user != null ) { request.setAttribute("loginInfo" , "200" ); } else { request.setAttribute("loginInfo" , "403" ); } request.getRequestDispatcher("/login.jsp" ).forward(request, response); } @Override protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }