EasyCaptcha介绍

EasyCaptcha是一款开源的验证码生成工具其支持多种类型的验证码
例如gif、中文、算术等,并且简单易用
本文只简单介绍其在java前后端分离项目的应用
更多内容请参考官方文档:具体内容可参考其官方文档

前后端项目使用EasyCaptcha

  1. 引入依赖
    官方建议与redis一起使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <!--EasyCaptcha依赖-->
    <dependency>
    <groupId>com.github.whvcse</groupId>
    <artifactId>easy-captcha</artifactId>
    <version>1.6.2</version>
    </dependency>

    <!--Redis依赖-->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
  2. redis配置
    配置连接redis信息,

    1
    2
    3
    4
    5
    6
    7
    spring:
    data:
    redis:
    host: <hostname>
    password: <password>
    port: <port>
    database: 0

生成图片验证码

  1. 项目场景

    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
    //"图像验证码"
    @Data
    @AllArgsConstructor
    public class CaptchaVo {

    //验证码图片信息,这里并不指图片的url,而是图片本身
    private String image;

    //验证码key
    private String key;
    }



    @RestController
    @RequestMapping("/login")
    public class LoginController {

    @Autowired
    private LoginService loginService;

    //获取图形验证码
    @GetMapping("captcha")
    public Result<CaptchaVo> getCaptcha() {
    CaptchaVo result=loginService.getCaptcha();
    return Result.ok(result);
    }
    }
  2. 逻辑实现
    设置图形验证码的参数:长,宽,验证码位数
    生成验证码
    设置验证码的key
    将验证码存入redis,设置过期时间
    向前端返回验证码图片信息

    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
    //service接口
    public interface LoginService {

    CaptchaVo getCaptcha();
    }


    //service接口实现类
    @Service
    public class LoginServiceImpl implements LoginService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public CaptchaVo getCaptcha() {
    //设置图形验证码的参数:长,宽,验证码位数
    SpecCaptcha specCaptcha = new SpecCaptcha(130, 48, 4);

    //生成二进制验证码图片,并将其代表的验证码转换为小写
    String code= specCaptcha.text().toLowerCase();
    //设置验证码的key
    String key = "admin:login:" +UUID.randomUUID();

    //将验证码存入redis,设置过期时间为1分钟
    stringRedisTemplate.opsForValue().set(key,code,60, TimeUnit.SECONDS);

    //返回验证码图片信息
    return new CaptchaVo(specCaptcha.toBase64(),key);
    }
    }

    知识点:

    • base64能将任意二进制的内容编码成一个字符串
    • specCaptcha.toBase64()会将生成的二进制验证码图片编码为字符串
    • 前端只需要在图片标签<img src="">,src中填入生成的值即可看到验证码图片

校验验证码

  1. 项目场景
    controller
    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
    @Data
    //登录信息
    public class LoginVo {

    /* @Schema(description="用户名")
    private String username;

    @Schema(description="密码")
    private String password; */

    @Schema(description="验证码key")
    private String captchaKey;

    @Schema(description="验证码code")
    private String captchaCode;
    }

    @RestController
    @RequestMapping("/login")
    public class LoginController {

    @Autowired
    private LoginService loginService;

    //登录
    @PostMapping("login")
    public Result<String> login(@RequestBody LoginVo loginVo) {
    String token=loginService.login(loginVo);
    return Result.ok(token);
    }
    }
  1. 验证功能实现
    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
    //service接口
    public interface LoginService {

    String login(LoginVo loginVo);
    }


    //service接口实现类
    @Override
    public String login(LoginVo loginVo) {
    //1. 判断前端所传验证码是否为空
    if(loginVo.getCaptchaCode()==null){
    //return "请输入验证码";
    //抛出异常:验证码为空
    throw new LoginExeception("验证码为空");
    }

    //2. 从redis中获取验证码
    String code = stringRedisTemplate.opsForValue().get(loginVo.getCaptchaKey());

    //3. 判断验证码是否过期
    if(code==null){
    //return "验证码已过期";
    //抛出异常:验证码已过期
    throw new LoginExeception("验证码已过期");
    }

    //4. 判断验证码是否正确
    //忽略大小写逻辑:前面的逻辑中将验证码转换为小写,所以这里也需要将用户输入的验证码转换为小写
    if(!code.equals(loginVo.getCaptchaCode().toLowerCase())){
    //return "验证码错误";
    //抛出异常:验证码错误
    throw new LoginExeception("验证码错误");
    }

    //5. 验证码正确,执行其他登录验证逻辑

    return "";
    }