SpringBoot+Hutool实现图片验证码

发布时间:2024年01月10日

图片验证码在注册、登录、交易、交互等各类场景中都发挥着巨大作用,能够防止操作者利用机器进行暴力破解、恶意注册、滥用服务、批量化操作和自动发布等行为。

在这里插入图片描述
创建一个实体类封装,给前端返回的验证码数据:

@Data
public class ValidateCodeVo {

    private String codeKey ;        // 验证码的key
    private String codeValue ;      // 图片验证码对应的字符串数据

}

业务层代码实现:

public interface ValidateCodeService {

    // 获取验证码图片
    public abstract ValidateCodeVo generateValidateCode();

}
@Service
public class ValidateCodeServiceImpl implements ValidateCodeService {
?
    @Autowired
    private RedisTemplate<String , String> redisTemplate ;
?
    @Override
    public ValidateCodeVo generateValidateCode() {
?
        // 使用hutool工具包中的工具类生成图片验证码
        //参数:宽  高  验证码位数 干扰线数量
        CircleCaptcha circleCaptcha = CaptchaUtil.createCircleCaptcha(150, 48, 4, 20);
        String codeValue = circleCaptcha.getCode();
        String imageBase64 = circleCaptcha.getImageBase64();
?
        // 生成uuid作为图片验证码的key
        String codeKey = UUID.randomUUID().toString().replace("-", "");
?
        // 将验证码存储到Redis中
        redisTemplate.opsForValue().set("user:login:validatecode:" + codeKey , codeValue , 5 , TimeUnit.MINUTES);
?
        // 构建响应结果数据
        ValidateCodeVo validateCodeVo = new ValidateCodeVo() ;
        validateCodeVo.setCodeKey(codeKey);
        validateCodeVo.setCodeValue("data:image/png;base64," + imageBase64);
?
        // 返回数据
        return validateCodeVo;
    }
?
}

在Controller中添加获取验证码接口方法:

@Autowired
private ValidateCodeService validateCodeService;

@GetMapping(value = "/generateValidateCode")
public Result<ValidateCodeVo> generateValidateCode() {
    ValidateCodeVo validateCodeVo = validateCodeService.generateValidateCode();
    return Result.build(validateCodeVo , ResultCodeEnum.SUCCESS) ;
}

在登录的业务层实现验证码校验:

 /**
     * 用户登录
     * @param loginDto
     * @return
     */
    @Override
    public LoginVo login(LoginDto loginDto) {
        //获取输入的验证码和存储到redis的key名称
        String captcha = loginDto.getCaptcha();
        String key = loginDto.getCodeKey();

        //根据获取的redis的key 查询redis里面存储的验证码
        String redisCode = redisTemplate.opsForValue().get("user:validate" + key);

        // 比较输入的和redis存储验证码是否一致
        if(StrUtil.isEmpty(redisCode) || !StrUtil.equalsIgnoreCase(redisCode,captcha)){
            //提示用户,校验失败
            throw new GuiguException(ResultCodeEnum.VALIDATECODE_ERROR);
        }

        // 如果一致,删除redis里面验证码
        redisTemplate.delete("user:validate" + key);

        // 1.获取提交的用户名
        String userName = loginDto.getUserName();

        // 2.根据用户名查询用户表
        SysUser sysUser = sysUserMapper.selectUserInfoByUserName(userName);

        // 3.如果根据用户名查不到对应的信息,用户不存在,返回错误信息
        if(sysUser == null){
            //throw new RuntimeException("用户名不存在");
            throw new GuiguException(ResultCodeEnum.LOGIN_ERROR);
        }

        // 4.根据用户名查询用户信息,用户存在
        // 5.获取输入的密码,比较输入的密码和数据库的密码是否一致
        String database_assword = sysUser.getPassword();
        // 把输入的密码进行加密 再比较数据库的密码
        String input_password = DigestUtils.md5DigestAsHex(loginDto.getPassword().getBytes());

        //比较
        if(!input_password.equals(database_assword)){
//            throw new RuntimeException("密码不正确");
            throw new GuiguException(ResultCodeEnum.LOGIN_ERROR);
        }

        // 6.如果密码一致,登陆成功,如果你密码不一致登陆失败
        // 7.登陆成功,生产用户的唯一标识token
        String token = UUID.randomUUID().toString().replaceAll("-", "");

        // 8.把登陆成功的用户信息放到redis里面
        // key:token value:用户信息

        redisTemplate.opsForValue().set("user:login"+token,JSON.toJSONString(sysUser),7, TimeUnit.DAYS);
        // 9.返回loginvo对象
        LoginVo loginVo = new LoginVo();
        loginVo.setToken(token);
        return loginVo;
    }
文章来源:https://blog.csdn.net/qq_63140630/article/details/135472294
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。