后台生成验证码前台显示,防止前端绕过
后台通过代码生成验证码,保存在session中,用户登录的时候验证.
以下提供两种方式,都大同小异;
皆为参考他人文章,因时间较长,文章原文链接丢失,还请见谅!
第一种:
@RequestMapping(value = "authCode") public void getAuthCode(HttpServletRequest request, HttpServletResponse response,HttpSession session) throws IOException { int width = 63; int height = 37; Random random = new Random(); //设置response头信息 //禁止缓存 response.setHeader("Pragma", "No-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0); //生成缓冲区image类 BufferedImage image = new BufferedImage(width, height, 1); //产生image类的Graphics用于绘制操作 Graphics g = image.getGraphics(); //Graphics类的样式 g.setColor(this.getRandColor(200, 250)); g.setFont(new Font("Times New Roman",0,28)); g.fillRect(0, 0, width, height); //绘制干扰线 for(int i=0;i<40;i++){ g.setColor(this.getRandColor(130, 200)); int x = random.nextInt(width); int y = random.nextInt(height); int x1 = random.nextInt(12); int y1 = random.nextInt(12); g.drawLine(x, y, x + x1, y + y1); } //绘制字符 String strCode = ""; for(int i=0;i<4;i++){ String rand = String.valueOf(random.nextInt(10)); strCode = strCode + rand; g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110))); g.drawString(rand, 13*i+6, 28); } //将字符保存到session中用于前端的验证 session.setAttribute("strCode", strCode); g.dispose(); ImageIO.write(image, "JPEG", response.getOutputStream()); response.getOutputStream().flush(); } Color getRandColor(int fc,int bc){ Random random = new Random(); if(fc>255) fc = 255; if(bc>255) bc = 255; int r = fc + random.nextInt(bc - fc); int g = fc + random.nextInt(bc - fc); int b = fc + random.nextInt(bc - fc); return new Color(r,g,b); }
调用方式:
<img src="authCode" id="codeImg"> <a href="javascript:;" onclick="chageCode()">看不清,换一张</a> <script> function chageCode(){ $("#codeImg").attr('src','authCode?abc='+Math.random()); } </script>
实现效果:
第二种:
@RequestMapping(value = "authCode") public void getAuthCode(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws IOException { response.setContentType("image/jpeg"); response.setHeader("Pragma", "no-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0); ValidateCode vCode = new ValidateCode(100,30,4,60); session.removeAttribute("validateCode"); vCode.write(response.getOutputStream()); session.setAttribute("strCode", vCode.getCode()); vCode.write(response.getOutputStream()); }
ValidateCode类:
import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Random; import javax.imageio.ImageIO; /** * 验证码生成器 */ public class ValidateCode { // 图片的宽度。 private int width = 160; // 图片的高度。 private int height = 50; // 验证码字符个数 private int codeCount = 6; // 验证码干扰线数 private int lineCount = 150; // 验证码 private static String code = null; // 验证码图片Buffer private BufferedImage buffImg = null; private char[] codeSequence = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; public ValidateCode() { this.createCode(); } /** * * @param width * 图片宽 * @param height * 图片高 */ public ValidateCode(int width, int height) { this.width = width; this.height = height; this.createCode(); } /** * * @param width * 图片宽 * @param height * 图片高 * @param codeCount * 字符个数 * @param lineCount * 干扰线条数 */ public ValidateCode(int width, int height, int codeCount, int lineCount) { this.width = width; this.height = height; this.codeCount = codeCount; this.lineCount = lineCount; this.createCode(); } public void createCode() { int x = 0, fontHeight = 0, codeY = 0; int red = 0, green = 0, blue = 0; x = width / (codeCount + 2);// 每个字符的宽度 fontHeight = height - 2;// 字体的高度 codeY = height - 4; // 图像buffer buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g = buffImg.createGraphics(); // 生成随机数 Random random = new Random(); // 将图像填充为白色 g.setColor(Color.WHITE); g.fillRect(0, 0, width, height); // 创建字体 ImgFontByte imgFont = new ImgFontByte(); Font font = imgFont.getFont(fontHeight); g.setFont(font); for (int i = 0; i < lineCount; i++) { int xs = random.nextInt(width); int ys = random.nextInt(height); int xe = xs + random.nextInt(width / 8); int ye = ys + random.nextInt(height / 8); red = random.nextInt(255); green = random.nextInt(255); blue = random.nextInt(255); g.setColor(new Color(red, green, blue)); g.drawLine(xs, ys, xe, ye); } // randomCode记录随机产生的验证码 StringBuffer randomCode = new StringBuffer(); // 随机产生codeCount个字符的验证码。 for (int i = 0; i < codeCount; i++) { String strRand = String.valueOf(codeSequence[random.nextInt(codeSequence.length)]); // 产生随机的颜色值,让输出的每个字符的颜色值都将不同。 red = random.nextInt(255); green = random.nextInt(255); blue = random.nextInt(255); g.setColor(new Color(red, green, blue)); g.drawString(strRand, (i + 1) * x, codeY); // 将产生的四个随机数组合在一起。 randomCode.append(strRand); } // 将四位数字的验证码保存到Session中。 code = randomCode.toString(); } public void write(String path) throws IOException { OutputStream sos = new FileOutputStream(path); this.write(sos); } public void write(OutputStream sos) throws IOException { ImageIO.write(buffImg, "png", sos); sos.close(); } public BufferedImage getBuffImg() { return buffImg; } public String getCode() { return code; } } class ImgFontByte { public Font getFont(int fontHeight){ try { Font baseFont = Font.createFont(Font.ITALIC, new ByteArrayInputStream(hex2byte(getFontByteStr()))); return baseFont.deriveFont(Font.PLAIN, fontHeight); } catch (Exception e) { return new Font("Consola",Font.PLAIN, fontHeight); } } private byte[] hex2byte(String str) { if (str == null) return null; str = str.trim(); int len = str.length(); if (len == 0 || len % 2 == 1) return null; byte[] b = new byte[len / 2]; try { for (int i = 0; i < str.length(); i += 2) { b[i/2] = (byte) Integer.decode("0x" + str.substring(i, i + 2)).intValue(); } return b; } catch (Exception e) { return null; } } /** * ttf字体文件的十六进制字符串 * @return */ private String getFontByteStr(){ return null; } }
使用方式与第一种相同;
效果:
浙公网安备 33010602011771号