• 前后端分离项目验证码实现


    一、验证码实现流程:

    1、后端使用工具生成二维码(包括image的字符串和code字符);

    2、使用uuid生成唯一的key值,将key和code以键值对的形式存储到redis缓存中,设置过期时间;

    3、将image字符串和key值发送给前端,前端将image字符串转换成图片渲染到页面;

    4、将用户输入的验证码和接收的key值一起发送给后端;

    5、后端使用key从redis中读取code值,(转大小写)进行比对;

    6、比对成功执行相关操作,比对失败进行相关操作;

    二、代码实现

    1、使用 CaptchaUtil 工具类生成二维码,存入 redis 中并返回给前端

    1. @Service
    2. public class CheckCodeServiceImpl implements CheckCodeService {
    3. @Autowired
    4. RedisTemplate redisTemplate;
    5. @Override
    6. public CheckCode getCheckCode() {
    7. // 150、50为图形的长、宽。 4表示生成4位验证码,2表示干扰线是2位,并放入redis
    8. CircleCaptcha circleCaptcha = CaptchaUtil.createCircleCaptcha(150, 50, 4, 2);
    9. //code验证码
    10. String codeValue = circleCaptcha.getCode();
    11. //图片验证码
    12. String imageBase64 = circleCaptcha.getImageBase64();
    13. //添加文件头部
    14. //"data:images/png;base64,"+imageBase64 直接显示
    15. String img = "data:images/png;base64," +imageBase64;
    16. //生成唯一key
    17. String uuid = UUID.randomUUID().toString();
    18. String key = uuid.replace("-", "");
    19. //存入redis,并设置过期时间
    20. redisTemplate.opsForValue().set(key, codeValue, 3, TimeUnit.MINUTES);
    21. //封装返回对象
    22. CheckCode checkCode = new CheckCode();
    23. checkCode.setCheckImg(img);
    24. checkCode.setCheckMessage(key);
    25. return checkCode;
    26. }
    27. }

    2、前端接收并渲染到页面

    1. //js代码
    2. //验证
    3. const checkImg = ref("")
    4. const getCheckCode = async()=>{
    5. return request.get(`/checkCode/get`)
    6. }
    7. //html代码
    8. "login_span">
    9. 验证码:
    10. "user.checkCode" style="width: 210px;height:40px;margin-bottom:30px;" placeholder="Please input" />
    11. "width: 100px; height: 40px;margin-left: 10px;cursor:pointer;" :src="checkImg" :fit="fit"/>
  • 3、前端向后端发送校验请求并携带key和验证码

    1. //登录
    2. const user = reactive({
    3. username: "",
    4. password: "",
    5. //输入的验证码
    6. checkCode:"",
    7. //key
    8. checkMessage:""
    9. })
    10. async function(){
    11. const {data} = await request.post(`/auth/login`,user)
    12. }

    4、后端收到请求,进行校验

    1. @Override
    2. public String login(LoginDto loginDto) {
    3. //验证码验证
    4. String checkCode = loginDto.getCheckCode();
    5. String queryCode = redisTemplate.opsForValue().get(loginDto.getCheckMessage());
    6. //统一为小写比较
    7. String lowerCaseCheckCode = checkCode.toLowerCase();
    8. String lowerCasequeryCode = queryCode.toLowerCase();
    9. if(!lowerCaseCheckCode.equals(lowerCasequeryCode)){
    10. throw new RuntimeException("验证码错误");
    11. }
    12. //删除验证码缓存
    13. redisTemplate.delete(loginDto.getCheckMessage());
    14. //获取认证方法进行认证
    15. String username = loginDto.getUsername();
    16. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper().eq(User::getUsername, username);
    17. User user = userMapper.selectOne(queryWrapper);
    18. if(null == user){
    19. throw new RuntimeException("用户不存在");
    20. }
    21. //比较密码
    22. String passwordDb = user.getPassword();
    23. String password = loginDto.getPassword();
    24. boolean matches = passwordEncoder.matches(password, passwordDb);
    25. if(!matches){
    26. throw new RuntimeException("密码错误");
    27. }
    28. int id = user.getId();
    29. String userid = String.valueOf(id);
    30. //生成jwt
    31. String jwt = JwtUtils.createJWT(userid);
    32. //将用户信息转换成json数据
    33. String jsonString = JSON.toJSONString(user);
    34. //将用户信息存入redis
    35. redisTemplate.opsForValue().set("userId:"+userid,jsonString,30, TimeUnit.MINUTES);
    36. //返回给前端令牌
    37. return jwt;
    38. }

  • 相关阅读:
    如何获取GC(垃圾回收器)的STW(暂停)时间?
    Redis 主从复制
    K210(SiPEED MaixBit)MicroPython使用参考(十、MAX98357A的I2S驱动)
    融合差分进化和混合多策略的麻雀搜索算法
    IronSource 聚合广告平台接入踩坑日记——游戏声音消失
    Pytorch实现RNN预测模型并使用C++相应的ONNX模型推理
    SchedulingConfigurer教程,怎么使用Spring自带的可扩展定时任务调度接口
    React 函数组件
    [开源]一个低代码引擎,支持在线实时构建低码平台,支持二次开发
    【无标题】
  • 原文地址:https://blog.csdn.net/qh1112/article/details/140044232