SpringBoot整合Kaptcha 生成验证码

SpringBoot 整合 Kaptcha 实现 后台验证码问题

为什么要用验证码?

这个问题我以前也问过,当时我觉得验证码根本没啥用,就是一个摆设还浪费空间、时间,实则不然,小小验证码用途很大!它能够进行一次过滤,过滤掉那些机器人;用在注册可以防止机器注册是数据库爆炸,此外,也能够防止操作过于频繁。

为什么后端要实现验证码

验证码前端都可以实现为什么要用后端来?我某次再看帖子,这个帖子是这样子介绍的:前端验证码你可以理解为一层纱,后端验证码就是一栋墙,二者不在一个层次(可能不太准确)。学过一段爬虫,而且从事后端开发,当然知道可以直接调用接口实现功能,然而前端的验证码就真的成了虚设。。。

话不多说,开搞

1. 引入依赖
<dependency>
    <groupId>com.github.penggle</groupId>
    <artifactId>kaptcha</artifactId>
    <version>2.3.2</version>
</dependency>
2. 基本配置
@Component
public class KaptchaConfig {
    @Bean
    public DefaultKaptcha getKaptcha() {
        DefaultKaptcha kaptcha = new DefaultKaptcha();
        Properties properties = new Properties();
        //图片边框
        properties.setProperty("kaptcha.border", "no");
        //边框颜色
        properties.setProperty("kaptcha.border.color", "105,179,90");
        //字体颜色
        properties.setProperty("kaptcha.textproducer.font.color", "red");
        //设置图片的高
        properties.setProperty("kaptcha.image.width", "110");
        //设置字体大小
        properties.setProperty("kaptcha.textproducer.font.size", "30");
        // session key
        properties.setProperty("kaptcha.session.key", "code");
        // 验证码长度
        properties.setProperty("kaptcha.textproducer.char.length", "4");
        // 字体
        properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑");
        Config config = new Config(properties);
        kaptcha.setConfig(config);
        return kaptcha;
    }
}
3. controller配置

这里我们采用的是将图片转为base64,然后返回给前端,让前端转成图片

问题解答:

为什么采用base64传图片?

  1. session 问题无法解决,使用session 我第一时间也想到了,但是前后端分离Session就显得略微鸡肋,前端拉着改了三天,后来发现每次请求的session都不一样,没法获取验证码。
  2. 响应头问题,我也想过使用响应头去解决这个问题,但是前端说node貌似没法获取响应头。。。。。。

在此处被迫使用base64位

配置如下:

@RestController
@RequestMapping("/Kaptcha")
public class KaptchaController {
    @Autowired
    DefaultKaptcha defaultKaptcha;
    @Resource
    RedisUtil redisUtil;
    @RequestMapping("/defaultKaptcha")
    public Map<String,Object> defaultKaptcha() throws Exception {
        ByteArrayOutputStream  out;
        //生成UUID,作为条件,后续会讲到
        String key=UUID.randomUUID().toString();
        //生成验证码
        String text = defaultKaptcha.createText();
        System.out.println(text);
        BufferedImage image = defaultKaptcha.createImage(text);
        //这个是我们写的redis工具类,目的是为了更方便,这里表示存放到 redis里面,时间为 2小时
        redisUtil.set("code:"+key,text,60*60*2);
        out =new ByteArrayOutputStream();
        ImageIO.write(image,"jpg",out);
        Map<String,Object> map =new HashMap<>();
        BASE64Encoder base64Encoder=new BASE64Encoder();
        map.put("code-information",key);
        map.put("img", "data:image/jpg;base64,"+base64Encoder.encode(out.toByteArray()).trim().replace("\n","").replace("\r",""));
        return map;
    }
}
实际controller层
@PostMapping("/login")
@ResponseBody
@ApiOperation(value = "进行登录", notes = "进行登录")
@ApiImplicitParams({
        @ApiImplicitParam(name = "account", value = "账号", required = true),
        @ApiImplicitParam(name = "password", value = "密码", required = true)
})
public Result login(String account, String password, String code, HttpServletRequest request) {
    if (code == null || code.length() != 4) {
        return Result.fail("请输入正确验证码");
    }
    //此处说明验证码的格式理论上是正确的
    if (request.getHeader("code-information") == null ){
        return Result.fail("请求失败");
    }
    //此处说明存在请求体
    String head = request.getHeader("code-information");
    if (!redisUtil.hasKey("code:"+head)){
        //说明不存在
        return Result.fail("验证码错误");
    }
    if (!redisUtil.get("code:"+head).equals(code)){
        return Result.fail("验证码错误");
    }
    redisUtil.del("code:"+head);
    
    return userService.login(account, password);
}

中间省略了其他的判断逻辑

细说:

这里大家可以看到有一个HttpServletRequest,用它去获取请求头, 获取的请求头位code-information,心系的观众老爷们就发现了在生成验证码的时候也生成了UUID,最后存放的时候键就是code-information,这里是通过前端设置请求头,然后将UUID放进去,然后通过redis进行验证。

大坑

JDK一定要使用JDK8 这个版本,因为JDK8 之后就不支持BASE64Encoder了,而是以 BaseUtil进行代替,据说是更加的安全

BASE64Encoder 的包

import sun.misc.BASE64Encoder;
末尾想问:

谁有更好的方法,希望给我讲讲,解决疑惑!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值