首页 后端 Spring Boot 正文

前后端分离,SpringBoot如何实现验证码操作

           验证码的功能是防止非法用户恶意去访问登录接口而设置的一个功能,今天我们就来看看在前后端分离的项目中,SpringBoot是如何提供服务的。        SpringBoot版本    本文基于的Spring Boot的版本是2.6.7 。    引入依赖    captcha一款

验证码的功能是防止非法用户恶意去访问登录接口而设置的一个功能,今天我们就来看看在前后端分离的项目中,SpringBoot是如何提供服务的。

SpringBoot版本

本文基于的Spring Boot的版本是2.6.7 。

引入依赖

captcha一款超简单的验证码生成,还挺好玩的.还有中文验证码,动态验证码. 。在项目中pom.xml配置文件中添加依赖,如下:

<!--验证码-->
<dependency>
    <groupId>com.github.whvcse</groupId>
    <artifactId>easy-captcha</artifactId>
    <version>1.6.2</version>
</dependency>

实现思路

  • 把生成的验证码结果保存到redis缓存中,并设置过期时间。

  • 前端通过提交验证码和key,其中key就是保存到redis中的键,通过这个键获取到对应的值,再与前端提交的值对比,相同就通过验证。

    实现过程

    新建验证码枚举类

    由于captcha这款验证码提供了好几种验证码方法,有中文验证码,动态验证码,算术验证码等等,新建一个验证码每周类存放这几种验证码类型。代码如下:

    public enum LoginCodeEnum {
      /**
       * 算数
       */
      ARITHMETIC,
      /**
       * 中文
       */
      CHINESE,
      /**
       * 中文闪图
       */
      CHINESE_GIF,
      /**
       * 闪图
       */
      GIF,
      SPEC
    }

    定义验证码配置信息

    该类是定义验证码的基本信息,例如高度、宽度、字体类型、验证码类型等等、并且我们把它转成通过SpringBoot配置文件类型来定义更加方便。

    @Data
    public class LoginCode {
    
      /**
       * 验证码配置
       */
      private LoginCodeEnum codeType;
      /**
       * 验证码有效期 分钟
       */
      private Long expiration = 2L;
      /**
       * 验证码内容长度
       */
      private int length = 2;
      /**
       * 验证码宽度
       */
      private int width = 111;
      /**
       * 验证码高度
       */
      private int height = 36;
      /**
       * 验证码字体
       */
      private String fontName;
      /**
       * 字体大小
       */
      private int fontSize = 25;
    
      /**
       * 验证码前缀
       * @return
       */
      private  String   codeKey;
    
      public LoginCodeEnum getCodeType() {
          return codeType;
      }
    }

    把配置文件转换Pojo类的统一配置类

    @Configuration
    public class ConfigBeanConfiguration {
    
      @Bean
      @ConfigurationProperties(prefix = "login")
      public LoginProperties loginProperties() {
          return new LoginProperties();
      }
    }

    定义验证逻辑生成类

    @Data
    public class LoginProperties {
    
      private LoginCode loginCode;
    
      /**
       * 获取验证码生产类
       * @return
       */
      public Captcha getCaptcha(){
          if(Objects.isNull(loginCode)){
              loginCode = new LoginCode();
              if(Objects.isNull(loginCode.getCodeType())){
                  loginCode.setCodeType(LoginCodeEnum.ARITHMETIC);
              }
    
          }
          return switchCaptcha(loginCode);
      }
    
      /**
       * 依据配置信息生产验证码
       * @param loginCode
       * @return
       */
      private Captcha switchCaptcha(LoginCode loginCode){
          Captcha captcha = null;
          synchronized (this){
              switch (loginCode.getCodeType()){
                  case ARITHMETIC:
                      captcha = new FixedArithmeticCaptcha(loginCode.getWidth(),loginCode.getHeight());
                      captcha.setLen(loginCode.getLength());
                      break;
                  case CHINESE:
                      captcha = new ChineseCaptcha(loginCode.getWidth(),loginCode.getHeight());
                      captcha.setLen(loginCode.getLength());
                      break;
                  case CHINESE_GIF:
                      captcha = new ChineseGifCaptcha(loginCode.getWidth(),loginCode.getHeight());
                      captcha.setLen(loginCode.getLength());
                      break;
                  case GIF:
                      captcha = new GifCaptcha(loginCode.getWidth(),loginCode.getHeight());
                      captcha.setLen(loginCode.getLength());
                      break;
                  case SPEC:
                      captcha = new SpecCaptcha(loginCode.getWidth(),loginCode.getHeight());
                      captcha.setLen(loginCode.getLength());
                  default:
                      System.out.println("验证码配置信息错误!正确配置查看 LoginCodeEnum ");
    
              }
          }
          if(StringUtils.isNotBlank(loginCode.getFontName())){
              captcha.setFont(new Font(loginCode.getFontName(),Font.PLAIN,loginCode.getFontSize()));
          }
          return captcha;
      }
    
      static  class FixedArithmeticCaptcha extends ArithmeticCaptcha{
          public FixedArithmeticCaptcha(int width,int height){
              super(width,height);
          }
    
          @Override
          protected char[] alphas() {
              // 生成随机数字和运算符
              int n1 = num(1, 10), n2 = num(1, 10);
              int opt = num(3);
    
              // 计算结果
              int res = new int[]{n1 + n2, n1 - n2, n1 * n2}[opt];
              // 转换为字符运算符
              char optChar = "+-x".charAt(opt);
    
              this.setArithmeticString(String.format("%s%c%s=?", n1, optChar, n2));
              this.chars = String.valueOf(res);
    
              return chars.toCharArray();
          }
      }
    }

    在控制层上定义验证码生成接口

     @ApiOperation(value = "获取验证码", notes = "获取验证码")
      @GetMapping("/code")
      public Object getCode(){
    
          Captcha captcha = loginProperties.getCaptcha();
          String uuid = "code-key-"+IdUtil.simpleUUID();
          //当验证码类型为 arithmetic时且长度 >= 2 时,captcha.text()的结果有几率为浮点型
          String captchaValue = captcha.text();
          if(captcha.getCharType()-1 == LoginCodeEnum.ARITHMETIC.ordinal() && captchaValue.contains(".")){
              captchaValue = captchaValue.split("\\.")[0];
          }
          // 保存
          redisUtils.set(uuid,captchaValue,loginProperties.getLoginCode().getExpiration(), TimeUnit.MINUTES);
          // 验证码信息
          Map<String,Object> imgResult = new HashMap<String,Object>(2){{
              put("img",captcha.toBase64());
              put("uuid",uuid);
          }};
          return imgResult;
    
      }

    效果体验

    前后端分离,SpringBoot如何实现验证码操作  第1张

在前端调用接口

<template>
<div class="login-code">
  <img :src="codeUrl" @click="getCode">
</div>
</template>
<script>
    methods: {
    getCode() {
      getCodeImg().then(res => {
        this.codeUrl = res.data.img
        this.loginForm.uuid = res.data.uuid
      })
    },
    }
    created() {
    // 获取验证码
    this.getCode()
  },
 </script>

前后端分离,SpringBoot如何实现验证码操作  第2张

原文:https://juejin.cn/post/7098220209466523679
打赏
海报

本文转载自互联网,旨在分享有价值的内容,文章如有侵权请联系删除,部分文章如未署名作者来源请联系我们及时备注,感谢您的支持。

转载请注明本文地址:https://www.shouxicto.com/article/4511.html

相关推荐

总结下SpringData JPA 的常用语法

   SpringData JPA常用有两种写法,一个是用Jpa自带方法进行CRUD,适合简单查询场景、例如查询全部数据、根据某个字段查询,根据某字段排序等等。另一种是使用注解方式,@Query、@M...

Spring Boot 2022.06.08 0 198

为什么使用Spring Boot?

为什么使用Spring Boot?

           验证码的功能是防止非法用户恶意去访问登录接口而设置的一个功能,今天我们就来看看在前后端分离的项目中,Sprin...

Spring Boot 2022.06.08 0 142

SpringBoot中的异常处理

SpringBoot中的异常处理

           验证码的功能是防止非法用户恶意去访问登录接口而设置的一个功能,今天我们就来看看在前后端分离的项目中,Sprin...

Spring Boot 2022.06.01 0 183

发布评论

ainiaobaibaibaibaobaobeishangbishibizuichiguachijingchongjingdahaqiandaliandangaodw_dogedw_erhadw_miaodw_tuzidw_xiongmaodw_zhutouganbeigeiliguiguolaiguzhanghahahahashoushihaixiuhanheixianhenghorse2huaixiaohuatonghuaxinhufenjiayoujiyankeaikeliankouzhaokukuloukunkuxiaolandelinileimuliwulxhainiolxhlikelxhqiuguanzhulxhtouxiaolxhwahahalxhzanningwennonuokpinganqianqiaoqinqinquantouruoshayanshengbingshiwangshuaishuijiaosikaostar0star2star3taikaixintanshoutianpingtouxiaotuwabiweifengweiquweiwuweixiaowenhaowoshouwuxiangjixianhuaxiaoerbuyuxiaokuxiaoxinxinxinxinsuixixixuyeyinxianyinyueyouhenghengyuebingyueliangyunzanzhajizhongguozanzhoumazhuakuangzuohenghengzuoyi
支付宝
微信
赞助本站