一、验证码简介

  • 使用验证码的作用:防止恶意破解密码、刷票、论坛灌水、刷页、恶意注册、登录
    不使用验证码的问题

    • 使用程序破解某个用户的密码
    • 使用程序在论坛疯狂灌水
    • 使用程序刷票
    • 使用程序暴力实施所有提交数据的行为

      二、随机字符串验证码

  • 通过程序随机生成由大写字母、小写字母、数字、汉字组成的字符串

  • 优点:生成方便,识别难易程度可调节
  • 缺点:识别度不好掌握,识别度高容易被程序识别,识别度低用户体验较差

使用Java实现随机字符串验证码步骤

  • 创建画板:new BufferedImage()
  • 创建画笔:画板.getGraphics()
  • 随机生成内容:不同颜色的字符
  • 绘制内容:画笔.drawString()
  • 存为图片发送:ImageIO.write(画板,图片类型,输出流) ```java @Component @Slf4j public class RandomCodeUtil { private final Random random = new Random();

    public String randCode(int len) { if (len < 4) {

    1. len = 4;

    } // 生成字符串 StringBuilder code = new StringBuilder(); for (int i = 0; i < len; i++) {

    1. String str = "1234567890abcdefghijklmnopqrstuvwxyz";
    2. code.append(str.charAt(random.nextInt(str.length())));

    } return code.toString(); }

  1. public Color randColor() {
  2. int r = random.nextInt(256);
  3. int g = random.nextInt(256);
  4. int b = random.nextInt(256);
  5. return new Color(r, g, b);
  6. }
  7. public void createCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
  8. // 创建画板
  9. int height = 60;
  10. int width = 140;
  11. BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
  12. // 创建画笔
  13. Graphics2D pen = img.createGraphics();
  14. // 生成随机字符串
  15. String code = randCode(4);
  16. log.info(code);
  17. request.getSession().setAttribute("randomCode", code);
  18. pen.fillRect(0, 0, width, height);
  19. int fontSize = 14;
  20. pen.setFont(new Font("微软雅黑", Font.BOLD, fontSize + random.nextInt(5)));
  21. for (int i = 0; i < code.length(); i++) {
  22. pen.setColor(randColor());
  23. pen.drawString(code.charAt(i) + "", 20 + i * fontSize, (fontSize + height) / 2 + random.nextInt(5));
  24. }
  25. ServletOutputStream out = response.getOutputStream();
  26. ImageIO.write(img,"png", out);
  27. out.flush();
  28. out.close();
  29. }

}

  1. - controller实现
  2. ```java
  3. @GetMapping("/randomCode")
  4. private void randomCode() {
  5. try {
  6. randomCodeUtil.createCode(request, response);
  7. } catch (IOException e) {
  8. e.printStackTrace();
  9. }
  10. }
  11. @GetMapping("/checkRandomCode")
  12. private String checkRandomCode(String code) {
  13. String saveCode = (String) request.getSession().getAttribute("randomCode");
  14. log.info("randomCode");
  15. if (saveCode.equalsIgnoreCase(code)) {
  16. log.info("验证码正确");
  17. return "验证码正确";
  18. } else {
  19. log.info("验证码错误");
  20. return "验证码错误";
  21. }
  22. }

三、算数验证码

  1. @Component
  2. @Slf4j
  3. public class RandomCodeUtil {
  4. private final Random random = new Random();
  5. public String randCode(int len) {
  6. if (len < 4) {
  7. len = 4;
  8. }
  9. // 生成字符串
  10. StringBuilder code = new StringBuilder();
  11. for (int i = 0; i < len; i++) {
  12. String str = "1234567890abcdefghijklmnopqrstuvwxyz";
  13. code.append(str.charAt(random.nextInt(str.length())));
  14. }
  15. return code.toString();
  16. }
  17. public Color randColor() {
  18. int r = random.nextInt(256);
  19. int g = random.nextInt(256);
  20. int b = random.nextInt(256);
  21. return new Color(r, g, b);
  22. }
  23. public void createCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
  24. // 创建画板
  25. int height = 60;
  26. int width = 140;
  27. BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
  28. // 创建画笔
  29. Graphics2D pen = img.createGraphics();
  30. // 生成随机字符串
  31. String code = randCode(4);
  32. log.info(code);
  33. request.getSession().setAttribute("randomCode", code);
  34. pen.fillRect(0, 0, width, height);
  35. int fontSize = 14;
  36. pen.setFont(new Font("微软雅黑", Font.BOLD, fontSize + random.nextInt(5)));
  37. for (int i = 0; i < code.length(); i++) {
  38. pen.setColor(randColor());
  39. pen.drawString(code.charAt(i) + "", 20 + i * fontSize, (fontSize + height) / 2 + random.nextInt(5));
  40. }
  41. ServletOutputStream out = response.getOutputStream();
  42. ImageIO.write(img,"png", out);
  43. out.flush();
  44. out.close();
  45. }
  46. }
  • controller实现

    1. @GetMapping("/mathCode")
    2. private void mathCode() {
    3. try {
    4. mathCodeUtil.createCode(request, response);
    5. } catch (IOException e) {
    6. log.error("生成验证码错误");
    7. }
    8. }
    9. @GetMapping("/checkMathCode")
    10. private String checkMathCode(String code) {
    11. int saveCode = (Integer) request.getSession().getAttribute("mathCode");
    12. log.info(String.valueOf(saveCode));
    13. int sendCode = Integer.parseInt(code);
    14. if (saveCode == sendCode) {
    15. log.info("验证码正确");
    16. return "验证码正确";
    17. } else {
    18. log.info("验证码错误");
    19. return "验证码错误";
    20. }
    21. }

    四、kaptcha框架验证码

  • 优点:实用,根据帮助文档进行配置即可,不用考虑实现细节

    • 添加pom依赖

      1. <dependency>
      2. <groupId>com.github.axet</groupId>
      3. <artifactId>kaptcha</artifactId>
      4. <version>0.0.9</version>
      5. </dependency>
    • 实现配置类

      1. @Configuration
      2. public class KaptchaConfig {
      3. @Bean
      4. public DefaultKaptcha producer(){
      5. Properties properties = new Properties();
      6. properties.put("kaptcha.barber","no");
      7. properties.put("kaptcha.textproducer.font.color","black");
      8. properties.put("kaptcha.textproducer.char.space","5");
      9. Config config = new Config(properties);
      10. DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
      11. defaultKaptcha.setConfig(config);
      12. return defaultKaptcha;
      13. }
      14. }
    • 写controller接口 ```java @GetMapping(“/captchCode”) private void captchCode() { response.setHeader(“Cache-Control”, “no-store”); response.setContentType(“image/jpeg”); // 文字验证码 String text = producer.createText(); log.info(text); request.getSession().setAttribute(“captchCode”, text); // 图片验证码 BufferedImage image = producer.createImage(text); // 保存验证码到session request.getSession().setAttribute(Constants.KAPTCHA_SESSION_CONFIG_KEY, text); ServletOutputStream outputStream = null; try {

      1. outputStream = response.getOutputStream();
      2. ImageIO.write(image, "jpg", outputStream);

      } catch (IOException e) {

      1. e.printStackTrace();

      } IOUtils.closeQuietly(outputStream); }

  1. @GetMapping("/checkCapchaCode")
  2. private String checkCapchaCode(String code) {
  3. String saveCode = (String) request.getSession().getAttribute("captchCode");
  4. log.info(saveCode);
  5. if (saveCode.equalsIgnoreCase(code)) {
  6. log.info("验证码正确");
  7. return "验证码正确";
  8. } else {
  9. log.info("验证码错误");
  10. return "验证码错误";
  11. }
  12. }

```

五、滑块验证码——阿里云提供

  • 整合流程

    • 阿里云控制台搜索云盾,开通验证码服务
    • 新建一个验证码配置,生成一个HTML的demo
    • 根据接入文档,编写调用代码
    • 前台页面调用并验证

      六、图形验证码——腾讯云提供

  • 整合流程

    • 登录腾讯验证码接入平台
    • 新建验证码配置
    • 根据接入文档,编写调用代码
    • 前台页面调用并验证