一、Google Kaptcha
1、简介
kaptcha 是一个非常实用的验证码生成工具。有了它,你可以生成各种样式的验证码,因为它是可配置的。kaptcha工作的原理是调用 com.google.code.kaptcha.servlet.KaptchaServlet,生成一个图片。同时将生成的验证码字符串放到 HttpSession中。
使用kaptcha可以方便的配置:
- 验证码的字体
- 验证码字体的大小
- 验证码字体的字体颜色
- 验证码内容的范围(数字,字母,中文汉字!)
- 验证码图片的大小,边框,边框粗细,边框颜色
- 验证码的干扰线(可以自己继承com.google.code.kaptcha.NoiseProducer写一个自定义的干扰线)
- 验证码的样式(鱼眼样式、3D、普通模糊……当然也可以继承com.google.code.kaptcha.GimpyEngine自定义样式)
2、maven依赖
<dependency><groupId>pro.fessional</groupId><artifactId>kaptcha</artifactId><version>2.3.3</version>
</dependency>
<dependency><groupId>com.jhlabs</groupId><artifactId>filters</artifactId><version>2.0.235</version>
</dependency>
3、验证码配置类
import java.util.Properties;import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;@Component
public class KaptchaConfig {@Beanpublic DefaultKaptcha getDefaultKaptcha() {DefaultKaptcha defaultKaptcha = new DefaultKaptcha();Properties properties = new Properties();// 图片边框properties.setProperty("kaptcha.border", "no");// 边框颜色properties.setProperty("kaptcha.border.color", "black");//边框厚度properties.setProperty("kaptcha.border.thickness", "1");// 图片宽properties.setProperty("kaptcha.image.width", "200");// 图片高properties.setProperty("kaptcha.image.height", "50");//图片实现类properties.setProperty("kaptcha.producer.impl", "com.google.code.kaptcha.impl.DefaultKaptcha");//文本实现类properties.setProperty("kaptcha.textproducer.impl", "com.google.code.kaptcha.text.impl.DefaultTextCreator");//文本集合,验证码值从此集合中获取properties.setProperty("kaptcha.textproducer.char.string", "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");//验证码长度properties.setProperty("kaptcha.textproducer.char.length", "4");//字体properties.setProperty("kaptcha.textproducer.font.names", "宋体");//字体颜色properties.setProperty("kaptcha.textproducer.font.color", "black");//文字间隔properties.setProperty("kaptcha.textproducer.char.space", "5");//干扰实现类properties.setProperty("kaptcha.noise.impl", "com.google.code.kaptcha.impl.DefaultNoise");//干扰颜色properties.setProperty("kaptcha.noise.color", "blue");//干扰图片样式properties.setProperty("kaptcha.obscurificator.impl", "com.google.code.kaptcha.impl.WaterRipple");//背景实现类properties.setProperty("kaptcha.background.impl", "com.google.code.kaptcha.impl.DefaultBackground");//背景颜色渐变,结束颜色properties.setProperty("kaptcha.background.clear.to", "white");//文字渲染器properties.setProperty("kaptcha.word.impl", "com.google.code.kaptcha.text.impl.DefaultWordRenderer");Config config = new Config(properties);defaultKaptcha.setConfig(config);return defaultKaptcha;}}
4、接口返回图片验证码
在获取验证码的类中直接引入配置类即可
/*** 验证码类:Google Kaptcha*/ @Autowired DefaultKaptcha defaultKaptcha;
/*** 获取图片验证码** @return* @throws Exception*/public RspObjectBO<VerifyCodeRspBO> verifyCodeGet(VerifyCodeReqBO reqBO) throws Exception {RspObjectBO<VerifyCodeRspBO> res = new RspObjectBO<>();VerifyCodeRspBO data = new VerifyCodeRspBO();String verifyId = CommonUtils.getUUID();String createText = defaultKaptcha.createText();log.info("验证码内容:{}", createText);BufferedImage bi = defaultKaptcha.createImage(createText);ByteArrayOutputStream stream = new ByteArrayOutputStream();ImageIO.write(bi, "jpeg", stream);String verifyCode = Base64.encode(stream.toByteArray());stream.flush();stream.close();RBucket<String> rBucket = redissonClient.getBucket(RedisKeyConstants.VerifyCodeKey + verifyId, StringCodec.INSTANCE);if (Objects.nonNull(reqBO.getDev_type()) && reqBO.getDev_type().equals(DeviceTypeEnum.Terminal_WX_Xcx.getType())) {rBucket = redissonClient.getBucket(RedisKeyConstants.VerifyCodeKey + reqBO.getDev_type() + verifyId, StringCodec.INSTANCE);}rBucket.set(createText, 3, TimeUnit.MINUTES);data.setVerifyid(verifyId);data.setVerifydata(verifyCode);res.setData(data);return res;}
二、自定义实现
import cn.hutool.core.codec.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.Random;public class RandomValidateCodeUtil {private static final String RANDOMCODEKEY = "RANDOMVALIDATECODEKEY";//放到session中的keyprivate static final Logger logger = LoggerFactory.getLogger(RandomValidateCodeUtil.class);// private String randString = "0123456789";//随机产生只有数字的字符串 private String//private String randString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";//随机产生只有字母的字符串private String randString = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";//随机产生数字与字母组合的字符串private int width = 95;// 图片宽private int height = 30;// 图片高private int lineSize = 40;// 干扰线数量private int stringNum = 4;// 随机产生字符数量private Random random = new SecureRandom();/*** 获得字体*/private Font getFont() {return new Font("Fixedsys", Font.CENTER_BASELINE, 18);}/*** 获得颜色*/private Color getRandColor(int fc, int bc) {if (fc > 255) {fc = 255;}if (bc > 255) {bc = 255;}int r = fc + random.nextInt(bc - fc - 16);int g = fc + random.nextInt(bc - fc - 14);int b = fc + random.nextInt(bc - fc - 18);return new Color(r, g, b);}/*** 生成随机图片 存储到session中*/public void getRandomCode(HttpServletRequest request, HttpServletResponse response) {HttpSession session = request.getSession();// BufferedImage类是具有缓冲区的Image类,Image类是用于描述图像信息的类BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);// 产生Image对象的Graphics对象,改对象可以在图像上进行各种绘制操作Graphics g = image.getGraphics();g.fillRect(0, 0, width, height);//图片大小g.setFont(new Font("Times New Roman", Font.ROMAN_BASELINE, 18));//字体大小g.setColor(getRandColor(110, 133));//字体颜色// 绘制干扰线for (int i = 0; i <= lineSize; i++) {drawLine(g);}// 绘制随机字符String randomString = "";for (int i = 1; i <= stringNum; i++) {randomString = drawString(g, randomString, i);}//将生成的随机字符串保存到session中session.removeAttribute(RANDOMCODEKEY);session.setAttribute(RANDOMCODEKEY, randomString);g.dispose();try {// 将内存中的图片通过流动形式输出到客户端ImageIO.write(image, "JPEG", response.getOutputStream());} catch (Exception e) {logger.error("将内存中的图片通过流动形式输出到客户端失败>>>> ", e);}}/*** 生成随机图片验证码*/private String getRandomCode() throws IOException {// BufferedImage类是具有缓冲区的Image类,Image类是用于描述图像信息的类BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);// 产生Image对象的Graphics对象,改对象可以在图像上进行各种绘制操作Graphics g = image.getGraphics();g.fillRect(0, 0, width, height);//图片大小g.setFont(new Font("Times New Roman", Font.ROMAN_BASELINE, 18));//字体大小g.setColor(getRandColor(110, 133));//字体颜色// 绘制干扰线for (int i = 0; i <= lineSize; i++) {drawLine(g);}// 绘制随机字符String randomString = "";for (int i = 1; i <= stringNum; i++) {randomString = drawString(g, randomString, i);}g.dispose();//返回base64图片ByteArrayOutputStream stream = new ByteArrayOutputStream();ImageIO.write(image, "jpeg", stream);String verifiCode = Base64.encode(stream.toByteArray());stream.flush();stream.close();return verifiCode;}/*** 绘制字符串*/private String drawString(Graphics g, String randomString, int i) {g.setFont(getFont());g.setColor(new Color(random.nextInt(101), random.nextInt(111), random.nextInt(121)));String rand = String.valueOf(getRandomString(random.nextInt(randString.length())));randomString += rand;g.translate(random.nextInt(3), random.nextInt(3));g.drawString(rand, 13 * i, 16);return randomString;}/*** 绘制干扰线*/private void drawLine(Graphics g) {int x = random.nextInt(width);int y = random.nextInt(height);int xl = random.nextInt(13);int yl = random.nextInt(15);g.drawLine(x, y, x + xl, y + yl);}/*** 获取随机的字符*/private String getRandomString(int num) {return String.valueOf(randString.charAt(num));}public static void main(String[] args) throws IOException {RandomValidateCodeUtil randomValidateCodeUtil = new RandomValidateCodeUtil();System.out.println(randomValidateCodeUtil.getRandomCode());}
}
@RequestMapping("getVerifiCode")@ResponseBodypublic void getVerifiCode(HttpServletRequest request, HttpServletResponse response) throws IOException {/*1.生成验证码2.把验证码上的文本存在session中3.把验证码图片发送给客户端*/ImageVerificationCode ivc = new ImageVerificationCode(); //用我们的验证码类,生成验证码类对象BufferedImage image = ivc.getImage(); //获取验证码request.getSession().setAttribute("text", ivc.getText()); //将验证码的文本存在session中ivc.output(image, response.getOutputStream());//将验证码图片响应给客户端}
三、Hutool工具类实现
1、Hutool工具简介
Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。
Hutool中的工具方法来自每个用户的精雕细琢,它涵盖了Java开发底层代码中的方方面面,它既是大型项目开发中解决小问题的利器,也是小型项目中的效率担当;
Hutool是项目中“util”包友好的替代,它节省了开发人员对项目中公用类和公用工具方法的封装时间,使开发专注于业务,同时可以最大限度的避免封装不完善带来的bug。
2、引入maven依赖
<dependency><groupId>com.xiaoleilu</groupId><artifactId>hutool-all</artifactId><version>3.2.3</version>
</dependency>
3、验证码功能介绍
验证码功能位于cn.hutool.captcha包中,核心接口为ICaptcha,此接口定义了以下方法:
●createCode 创建验证码,实现类需同时生成随机验证码字符串和验证码图片
●getCode 获取验证码的文字内容
●verify 验证验证码是否正确,建议忽略大小写
●write 将验证码写出到目标流中
其中write方法只有一个OutputStream,ICaptcha实现类可以根据这个方法封装写出到文件等方法。AbstractCaptcha为一个ICaptcha抽象实现类,此类实现了验证码文本生成、非大小写敏感的验证、写出到流和文件等方法,通过继承此抽象类只需实现createImage方法定义图形生成规则即可。
LineCaptcha线段干扰的验证码
//定义图形验证码的长和宽
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);//图形验证码写出,可以写出到文件,也可以写出到流
lineCaptcha.write("d:/line.png");
//输出code
Console.log(lineCaptcha.getCode());
//验证图形验证码的有效性,返回boolean值
lineCaptcha.verify("1234");//重新生成验证码
lineCaptcha.createCode();
lineCaptcha.write("d:/line.png");
//新的验证码
Console.log(lineCaptcha.getCode());
//验证图形验证码的有效性,返回boolean值
lineCaptcha.verify("1234");
CircleCaptcha圆圈干扰验证码
//定义图形验证码的长、宽、验证码字符数、干扰元素个数CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(200, 100, 4, 20);//CircleCaptcha captcha = new CircleCaptcha(200, 100, 4, 20);//图形验证码写出,可以写出到文件,也可以写出到流captcha.write("d:/circle.png");//验证图形验证码的有效性,返回boolean值captcha.verify("1234");
ShearCaptcha扭曲干扰验证码
//定义图形验证码的长、宽、验证码字符数、干扰线宽度ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(200, 100, 4, 4);//ShearCaptcha captcha = new ShearCaptcha(200, 100, 4, 4);//图形验证码写出,可以写出到文件,也可以写出到流captcha.write("d:/shear.png");//验证图形验证码的有效性,返回boolean值captcha.verify("1234");
自定义验证码
有时候标准的验证码不满足要求,比如我们希望使用纯字母的验证码、纯数字的验证码、加减乘除的验证码,此时我们就要自定义CodeGenerator
// 自定义纯数字的验证码(随机4位数字,可重复)
RandomGenerator randomGenerator = new RandomGenerator("0123456789", 4);
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);
lineCaptcha.setGenerator(randomGenerator);
// 重新生成code
lineCaptcha.createCode();
ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(200, 45, 4, 4);
// 自定义验证码内容为四则运算方式
captcha.setGenerator(new MathGenerator());
// 重新生成code
captcha.createCode();