使用java实现登录验证码(代码全)
程序员文章站
2022-04-16 15:02:16
...
一、先写一个验证码工具类
package com.yx.cus.util;import java.awt.BasicStroke;import java.awt.Color;import java.awt.Font;import java.awt.Graphics2D;import java.awt.image.BufferedImage;import java.io.IOException;import java.io.OutputStream;import java.util.Random;import javax.imageio.ImageIO;public class VerifyCode { private int w = 70; private int h = 35; private Random r = new Random(); // {"宋体", "华文楷体", "黑体", "华文新魏", "华文隶书", "微软雅黑", "楷体_GB2312"} private String[] fontNames = {"宋体", "华文楷体", "黑体", "微软雅黑", "楷体_GB2312"}; private String codes = "23456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ"; private Color bgColor = new Color(255, 255, 255); public static String text ; private Color randomColor () { int red = r.nextInt(150); int green = r.nextInt(150); int blue = r.nextInt(150); return new Color(red, green, blue); } private Font randomFont () { int index = r.nextInt(fontNames.length); String fontName = fontNames[index]; int style = r.nextInt(4); int size = r.nextInt(5) + 24; return new Font(fontName, style, size);//指定字体名称、样式和点大小,创建一个新 Font。 } //画干扰的线条 private void drawLine (BufferedImage image) { int num = 3;//画三条 Graphics2D g2 = (Graphics2D)image.getGraphics(); for(int i = 0; i < num; i++) { int x1 = r.nextInt(w); int y1 = r.nextInt(h); int x2 = r.nextInt(w); int y2 = r.nextInt(h); g2.setStroke(new BasicStroke(1.5F)); g2.setColor(Color.BLUE); g2.drawLine(x1, y1, x2, y2); } } private char randomChar () { int index = r.nextInt(codes.length()); return codes.charAt(index); } private BufferedImage createImage () { BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Graphics2D g2 = (Graphics2D)image.getGraphics(); g2.setColor(this.bgColor); g2.fillRect(0, 0, w, h); return image; } public BufferedImage getImage () { BufferedImage image = createImage(); Graphics2D g2 = (Graphics2D)image.getGraphics(); StringBuilder sb = new StringBuilder(); // 向图片中画4个字符 for(int i = 0; i < 4; i++) { String s = randomChar() + ""; sb.append(s); float x = i * 1.0F * w / 4; g2.setFont(randomFont()); g2.setColor(randomColor()); /** * 首字符的基线位于用户空间的 (x, h-5) 位置处 * 原点在左上角,X轴递增的方向是从左向右;Y轴是从上到下 * 在提供的坐标位于基线上最左边字符的情况下,可以从右到左呈现字形 * h-5表示y轴方向,向上偏移了5 */ g2.drawString(s, x, h-5); } this.text = sb.toString(); drawLine(image); return image; } public String getText () { return text; } public static void output (BufferedImage image, OutputStream out) throws IOException { ImageIO.write(image, "JPEG", out); } }
这个工具类我们主要使用两个方法:
1.通过getImage()方法来制作验证码,返回BufferedImage 类型的验证码
2.通过getText()方法获取验证码的文本,返回String类型
二。验证码的接口(controller)
/** * 验证码 * @param request * @return * @throws Exception */@RequestMapping(value = "/VC", method = RequestMethod.POST)@ResponseBodypublic void VC(HttpServletRequest request, HttpServletResponse response ) throws Exception{ VerifyCode code=new VerifyCode(); BufferedImage image = code.getImage(); //将验证码文本存到Redis vckey=IDUtil.nextId(); JedisClient.set(vckey, code.getText(),60); ImageIO.write(image,"jpg",response.getOutputStream()); }
该接口会返回前端一个验证码,是以流的形式返回的,在返回之前会生成一个唯一的标识赋给一个全局变量,用来在redis里存入该验证码的文本,以作后用,存入的文本有时间限制
三、获取验证码文本标识的接口(就是存入验证码文本的值)
/** * 验证码文本的标识 * @param request * @return * @throws Exception */ @RequestMapping(value = "/VCkey", method = RequestMethod.POST)@ResponseBodypublic String VCkey(HttpServletRequest request, HttpServletResponse response ) throws Exception{ System.out.println(vckey); return vckey; }
该接口主要就是把在redis里存验证码文本的键返回给前端,然后在登录的时候一起传回登录的接口
四、登录接口(试例)
String user_phone = reqstr.get("user_phone");//账号String user_pwd = reqstr.get("user_pwd");//密码String vc = reqstr.get("vc").toLowerCase();//用户输入的验证码String vckey = reqstr.get("vckey");//前端获取的验证码文本的键(标识)String vcode= (String)JedisClient.get(vckey);//通过标识从redis里获取验证码文本if(vc.equals(vcode.toLowerCase())) {//用户输入的验证码与redsi存的作比较 “验证码成功” }else if(vcode==null){ “验证码以过期” }else{ “验证码错误” }
补充:验证码的键(标识)也可以在前端生成,比如生成一个时间戳,在请求验证码的接口时作为参数传入,这样后台就可以少写一个接口和全局变量
相关文章:
以上就是使用java实现登录验证码(代码全)的详细内容,更多请关注其它相关文章!
上一篇: java中static关键字、父类子类加载执行顺序解析
下一篇: java二分法查找怎么实现