图片验证码实践

基本原理

现在无论是app还是web登录时一般都需要一个验证码,用来防止暴力破解,基本原理是,后端生产一个随机字符串,将字符串变成一个图片,将图片返回给前端显示,在验证时,前端在给后端传账号,密码的同时传这个验证码,为了能正确校验这个字符串,前端在获取这个验证码时需要生成一个uuid,后端依据uuid查找验证码进行校验。

前端工作

构造一个现实图片的控件,同时这个控件在点击时获取新的验证码,并刷新图片。
代码

import { makeStyles } from “@mui/styles”;
import { useState } from “react”;
import uuid from “react-uuid”;

const useStyles=makeStyles({
root:{
padding:‘16.5px 14px’,
margin:‘16px’
}
})

export default function ImageButton(props){
const [code,setCode]=useState(“”)
const classes=useStyles()
return <img src={props.src+“&”+code} onClick={()=>setCode(uuid())} className={classes.root} alt=“验证码”>

}
代码说明
最简单的函数控件
使用useStyle调整下位置。
控件只有一个img,src的属性就是后端返回的图片url。img增加一个点击事件,通过hook绑定一个随机数(code),点击时生成新的随机数,img的src属性就会变化,控件获取到新的图片,并且刷新控件。
后端工作

生成验证码图片。
//controller代码
@GetMapping(“code”)
public void getVerifyCode(@RequestParam(name = “uuid”,required = false)String uuid,
HttpServletResponse response){
try {
BufferedImage image = verifyCodeService.getCode(uuid).getData();
response.setContentType(“image/png”);
OutputStream os = response.getOutputStream();
ImageIO.write(image, “png”, os);
}catch (Exception e){
log.error(“”,e);
}
}

//service代码
public ResponseVO getCode(String uuid) {
if(StringUtils.isBlank(uuid)){
return ResponseVOWrapper.buildFail(UserEnum.VERIFYCODEERROR);
}

    Object[] objects = VerifyUtil.createImage();
    String code=(String) objects[0];
    BufferedImage image = (BufferedImage) objects[1];
    log.debug("uuid={},code={}",uuid,code);
    VerifyCodeDO verifyCodeDO=verifyCodeRepository.getByUUID(uuid);
    log.debug("{}",verifyCodeDO);
    if(verifyCodeDO==null){
        verifyCodeDO=new VerifyCodeDO();
        verifyCodeDO.setUuid(uuid);
        verifyCodeDO.setCode(code);
        verifyCodeRepository.addVerifyCode(verifyCodeDO);
    }else {
        verifyCodeDO.setSms("");
        verifyCodeDO.setLastTime(null);
        verifyCodeDO.setCode(code);
        verifyCodeRepository.updateVerifyCode(verifyCodeDO);
    }

    return ResponseVOWrapper.buildSuccess(image);
}

校验验证码

public Boolean checkCode(String uuid, String code) {
VerifyCodeDO verifyCodeDO= verifyCodeRepository.getByUUID(uuid);

    if(verifyCodeDO==null||StringUtils.isBlank(verifyCodeDO.getCode())){
        return false;
    }

    if(!verifyCodeDO.getCode().toLowerCase().equals(code.toLowerCase())){
        verifyCodeDO.setCode("");
        verifyCodeRepository.updateVerifyCode(verifyCodeDO);
        return false;
    }

    verifyCodeDO.setCode("");
    verifyCodeRepository.updateVerifyCode(verifyCodeDO);

    return true;
}

代码说明
生成随机字符串,根据字符串生成BufferImage,返回给前端。
生成的随机字符串,存入数据库,主键为前端给的uuid。
验证,使用uuid从数据库查询记录,并比对。正确的返回true,不正确的返回false,并且删除已有的字符串,并重新生成。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值