整合營銷服務商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          驗證碼這樣做,瞬間高出一個逼格

          行為驗證碼通過用戶的操作來完成驗證,常見的行為驗證碼有拖動式和點觸式,拖動式驗證就是根據(jù)圖片顯示,將指定的圖形拖動到指定位置完成驗證。而點觸式驗證碼就是通過鼠標點擊出示例中出現(xiàn)的圖形完成驗證。

          行為驗證碼應用

          今天推薦一款非常優(yōu)秀的行為驗證碼AJ-Captcha(項目地址https://gitee.com/anji-plus/captcha),這個項目包含了滑動拼圖和文字點選兩種類型的驗證碼,除了嵌入式交互,還提供了彈出式交互的方式,完全不影響原UI布局。

          AJ-Captcha的驗證流程如下:

          1. 用戶訪問登錄頁面,發(fā)送請求顯示行為驗證碼
          2. 用戶按照提示要求完成驗證碼拼圖/點擊
          3. 用戶提交表單,前端將第二步的輸出一同提交到后臺
          4. 驗證數(shù)據(jù)隨表單提交到后臺后,后臺需要調用captchaService.verification做二次校驗。
          5. 第4步返回校驗通過/失敗到產品應用后端,再返回到前端。如下圖所示。

          如果你是Maven開發(fā)者,使用起來非常方便,項目的維護人員已經將依賴推送至中央倉庫。只需要引入依賴就完成了90%的工作量。接下來只需要在登錄接口中進行二次驗證就可以了。

          項目集成了包括htmlvueflutteruni-appAndroid KotlinIOSphp等多種前端語言,可以輕松將AJ_Captcha集成到項目中。

          接下來我們以Spring Boot+html為例看看如何快速集成AJ_Captcha完成行為驗證碼的交互流程。

          第一步、Spring Boot中引入AJ_Captcha依賴

          <dependency>
              <groupId>com.anji-plus</groupId>
              <artifactId>spring-boot-starter-captcha</artifactId>
              <version>1.2.9</version>
          </dependency>

          AJ_Captcha默認實現(xiàn)了驗證碼生成和驗證接口,驗證碼生成接口的默認請求地址是/captcha/get,驗證接口的默認請求地址為/captcha/check。也就是說完成以上步驟,就可以提供給前端獲取和驗證驗證碼的接口了。如果你還想讓你的驗證碼生成的個性一點,可以配置以下屬性:

          # 滑動驗證,底圖路徑,不配置將使用默認圖片
          # 支持全路徑
          # 支持項目路徑,以classpath:開頭,取resource目錄下路徑,例:classpath:images/jigsaw
          aj.captcha.jigsaw=classpath:images/jigsaw
          # 滑動驗證,底圖路徑,不配置將使用默認圖片
          # 支持全路徑
          # 支持項目路徑,以classpath:開頭,取resource目錄下路徑,例:classpath:images/pic-click
          aj.captcha.pic-click=classpath:images/pic-click
          
          # 對于分布式部署的應用,我們建議應用自己實現(xiàn)CaptchaCacheService,比如用Redis或者memcache,
          # 參考CaptchaCacheServiceRedisImpl.java
          # 如果應用是單點的,也沒有使用redis,那默認使用內存。
          # 內存緩存只適合單節(jié)點部署的應用,否則驗證碼生產與驗證在節(jié)點之間信息不同步,導致失敗。
          # !!! 注意啦,如果應用有使用spring-boot-starter-data-redis,
          # 請打開CaptchaCacheServiceRedisImpl.java注釋。
          # redis ----->  SPI: 在resources目錄新建META-INF.services文件夾(兩層),參考當前服務resources。
          # 緩存local/redis...
          aj.captcha.cache-type=local
          # local緩存的閾值,達到這個值,清除緩存
          #aj.captcha.cache-number=1000
          # local定時清除過期緩存(單位秒),設置為0代表不執(zhí)行
          #aj.captcha.timing-clear=180
          #spring.redis.host=10.108.11.46
          #spring.redis.port=6379
          #spring.redis.password=
          #spring.redis.database=2
          #spring.redis.timeout=6000
          
          # 驗證碼類型default兩種都實例化。
          aj.captcha.type=default
          # 漢字統(tǒng)一使用Unicode,保證程序通過@value讀取到是中文,可通過這個在線轉換;yml格式不需要轉換
          # https://tool.chinaz.com/tools/unicode.aspx 中文轉Unicode
          # 右下角水印文字(我的水印)
          aj.captcha.water-mark=\u6211\u7684\u6c34\u5370
          # 右下角水印字體(不配置時,默認使用文泉驛正黑)
          # 由于宋體等涉及到版權,我們jar中內置了開源字體【文泉驛正黑】
          # 方式一:直接配置OS層的現(xiàn)有的字體名稱,比如:宋體
          # 方式二:自定義特定字體,請將字體放到工程resources下fonts文件夾,支持ttf\ttc\otf字體
          # aj.captcha.water-font=WenQuanZhengHei.ttf
          # 點選文字驗證碼的文字字體(文泉驛正黑)
          # aj.captcha.font-type=WenQuanZhengHei.ttf
          # 校驗滑動拼圖允許誤差偏移量(默認5像素)
          aj.captcha.slip-offset=5
          # aes加密坐標開啟或者禁用(true|false)
          aj.captcha.aes-status=true
          # 滑動干擾項(0/1/2)
          aj.captcha.interference-options=2
          
          aj.captcha.history-data-clear-enable=false
          
          # 接口請求次數(shù)一分鐘限制是否開啟 true|false
          aj.captcha.req-frequency-limit-enable=false
          # 驗證失敗5次,get接口鎖定
          aj.captcha.req-get-lock-limit=5
          # 驗證失敗后,鎖定時間間隔,s
          aj.captcha.req-get-lock-seconds=360
          # get接口一分鐘內請求數(shù)限制
          aj.captcha.req-get-minute-limit=30
          # check接口一分鐘內請求數(shù)限制
          aj.captcha.req-check-minute-limit=60
          # verify接口一分鐘內請求數(shù)限制
          aj.captcha.req-verify-minute-limit=60
          

          第二步、前端偽代碼調用接口

          1. 引入驗證碼的樣式以及驗證等文件
          2. 驗證碼獲取及驗證
          <script>
              $('#content').slideVerify({
              baseUrl:'http://localhost:8080/',  //服務器請求地址, 默認地址為安吉服務器;
              containerId:'btn',//pop模式 必填 被點擊之后出現(xiàn)行為驗證碼的元素id
              mode:'pop',     //展示模式
              imgSize : {       //圖片的大小對象,有默認值{ width: '310px',height: '155px'},可省略
                  width: '400px',
                  height: '200px',
              },
              barSize:{          //下方滑塊的大小對象,有默認值{ width: '310px',height: '50px'},可省略
                  width: '400px',
                  height: '40px',
              },
              beforeCheck:function(){  //檢驗參數(shù)合法性的函數(shù)  mode ="pop"有效
                  let flag = true;
                  //實現(xiàn): 參數(shù)合法性的判斷邏輯, 返回一個boolean值
                  return flag
              },
              ready : function() {},  //加載完畢的回調
              success : function(params) { //成功的回調
                  // params為返回的二次驗證參數(shù) 需要在接下來的實現(xiàn)邏輯回傳服務器
                  例如: login($.extend({}, params))
              },
              error : function() {}        //失敗的回調
          });
          </script>
          

          驗證碼驗證成功之后,會返回一個用于二次驗證的串碼。

          第三步,用戶登錄,二次驗證

          客戶端登錄的時候攜帶驗證成功后返回的串碼,在登錄接口中進行二次驗證,驗證流程完畢。

          @Autowired
          private CaptchaService captchaService;
          /**
            * 頁面獲取token
            * 大屏數(shù)據(jù)校驗
            * @param user
            * @return
            */
          @PostMapping("getWebToken")
          public ResultBean getWebToken(@RequestBody LoginUser user,String captchaVerification){
              ResultBean resultBean = new ResultBean();
              CaptchaVO captchaVO = new CaptchaVO();
              captchaVO.setCaptchaVerification(captchaVerification);
              ResponseModel responseModel = captchaService.verification(captchaVO);
              if(!responseModel.isSuccess()){
                  resultBean.fillCode(0,responseModel.getRepMsg());
                  return resultBean;
              }
              // 驗證通過后,繼續(xù)登錄流程
          }
          

          今天的內容就介紹到這里了,趁這個機會,試著使用這款高顏值的行為驗證碼來替換項目中的圖形驗證碼吧。

          ,工具類記錄

          原鏈接:https://blog.csdn.net/qq_37651267/article/details/99305573,非常感謝原鏈接博主

          此驗證碼的實現(xiàn)沒有用到太多的插件,話不多說直接上代碼,大家拿過去就可以用。

          1.驗證碼類

           package com.youyou.login.util.validatecode;
          
          import lombok.Data;
          
          /**
           * 驗證碼類
           */
          @Data
          public class VerifyCode {
          
              private String code;
          
              private byte[] imgBytes;
          
              private long expireTime;
          
          }
          
          

          2.驗證碼生成接口

           package com.youyou.login.util.validatecode;
          
          import java.io.IOException;
          import java.io.OutputStream;
          
          /**
           * 驗證碼生成接口
           */
          public interface IVerifyCodeGen {
          
              /**
               * 生成驗證碼并返回code,將圖片寫的os中
               *
               * @param width
               * @param height
               * @param os
               * @return
               * @throws IOException
               */
              String generate(int width, int height, OutputStream os) throws IOException;
          
              /**
               * 生成驗證碼對象
               *
               * @param width
               * @param height
               * @return
               * @throws IOException
               */
              VerifyCode generate(int width, int height) throws IOException;
          }
          
          

          3.驗證碼生成實現(xiàn)類

           package com.youyou.login.util.validatecode;
          
          import com.youyou.util.RandomUtils;
          import org.slf4j.Logger;
          import org.slf4j.LoggerFactory;
          
          import javax.imageio.ImageIO;
          import java.awt.*;
          import java.awt.image.BufferedImage;
          import java.io.ByteArrayOutputStream;
          import java.io.IOException;
          import java.io.OutputStream;
          import java.util.Random;
          
          /**
           * 驗證碼實現(xiàn)類
           */
          public class SimpleCharVerifyCodeGenImpl implements IVerifyCodeGen {
          
              private static final Logger logger = LoggerFactory.getLogger(SimpleCharVerifyCodeGenImpl.class);
          
              private static final String[] FONT_TYPES = { "\u5b8b\u4f53", "\u65b0\u5b8b\u4f53", "\u9ed1\u4f53", "\u6977\u4f53", "\u96b6\u4e66" };
          
              private static final int VALICATE_CODE_LENGTH = 4;
          
              /**
               * 設置背景顏色及大小,干擾線
               *
               * @param graphics
               * @param width
               * @param height
               */
              private static void fillBackground(Graphics graphics, int width, int height) {
                  // 填充背景
                  graphics.setColor(Color.WHITE);
                  //設置矩形坐標x y 為0
                  graphics.fillRect(0, 0, width, height);
          
                  // 加入干擾線條
                  for (int i = 0; i < 8; i++) {
                      //設置隨機顏色算法參數(shù)
                      graphics.setColor(RandomUtils.randomColor(40, 150));
                      Random random = new Random();
                      int x = random.nextInt(width);
                      int y = random.nextInt(height);
                      int x1 = random.nextInt(width);
                      int y1 = random.nextInt(height);
                      graphics.drawLine(x, y, x1, y1);
                  }
              }
          
              /**
               * 生成隨機字符
               *
               * @param width
               * @param height
               * @param os
               * @return
               * @throws IOException
               */
              @Override
              public String generate(int width, int height, OutputStream os) throws IOException {
                  BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                  Graphics graphics = image.getGraphics();
                  fillBackground(graphics, width, height);
                  String randomStr = RandomUtils.randomString(VALICATE_CODE_LENGTH);
                  createCharacter(graphics, randomStr);
                  graphics.dispose();
                  //設置JPEG格式
                  ImageIO.write(image, "JPEG", os);
                  return randomStr;
              }
          
              /**
               * 驗證碼生成
               *
               * @param width
               * @param height
               * @return
               */
              @Override
              public VerifyCode generate(int width, int height) {
                  VerifyCode verifyCode = null;
                  try (
                          //將流的初始化放到這里就不需要手動關閉流
                          ByteArrayOutputStream baos = new ByteArrayOutputStream();
                  ) {
                      String code = generate(width, height, baos);
                      verifyCode = new VerifyCode();
                      verifyCode.setCode(code);
                      verifyCode.setImgBytes(baos.toByteArray());
                  } catch (IOException e) {
                      logger.error(e.getMessage(), e);
                      verifyCode = null;
                  }
                  return verifyCode;
              }
          
              /**
               * 設置字符顏色大小
               *
               * @param g
               * @param randomStr
               */
              private void createCharacter(Graphics g, String randomStr) {
                  char[] charArray = randomStr.toCharArray();
                  for (int i = 0; i < charArray.length; i++) {
                      //設置RGB顏色算法參數(shù)
                      g.setColor(new Color(50 + RandomUtils.nextInt(100),
                              50 + RandomUtils.nextInt(100), 50 + RandomUtils.nextInt(100)));
                      //設置字體大小,類型
                      g.setFont(new Font(FONT_TYPES[RandomUtils.nextInt(FONT_TYPES.length)], Font.BOLD, 26));
                      //設置x y 坐標
                      g.drawString(String.valueOf(charArray[i]), 15 * i + 5, 19 + RandomUtils.nextInt(8));
                  }
              }
          }
          
          


          4.工具類

           package com.youyou.util;
          
          import java.awt.*;
          import java.util.Random;
          
          public class RandomUtils extends org.apache.commons.lang3.RandomUtils {
          
              private static final char[] CODE_SEQ = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J',
                      'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
                      'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', '8', '9' };
          
              private static final char[] NUMBER_ARRAY = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
          
              private static Random random = new Random();
          
              public static String randomString(int length) {
                  StringBuilder sb = new StringBuilder();
                  for (int i = 0; i < length; i++) {
                      sb.append(String.valueOf(CODE_SEQ[random.nextInt(CODE_SEQ.length)]));
                  }
                  return sb.toString();
              }
          
              public static String randomNumberString(int length) {
                  StringBuilder sb = new StringBuilder();
                  for (int i = 0; i < length; i++) {
                      sb.append(String.valueOf(NUMBER_ARRAY[random.nextInt(NUMBER_ARRAY.length)]));
                  }
                  return sb.toString();
              }
          
              public static Color randomColor(int fc, int bc) {
                  int f = fc;
                  int b = bc;
                  Random random = new Random();
                  if (f > 255) {
                      f = 255;
                  }
                  if (b > 255) {
                      b = 255;
                  }
                  return new Color(f + random.nextInt(b - f), f + random.nextInt(b - f), f + random.nextInt(b - f));
              }
          
              public static int nextInt(int bound) {
                  return random.nextInt(bound);
              }
          }
          
          

          經過以上代碼,我們的驗證碼生成功能基本上已經實現(xiàn)了,現(xiàn)在還需要一個controller來調用它。

               @ApiOperation(value = "驗證碼")
              @GetMapping("/verifyCode")
              public void verifyCode(HttpServletRequest request, HttpServletResponse response) {
                  IVerifyCodeGen iVerifyCodeGen = new SimpleCharVerifyCodeGenImpl();
                  try {
                      //設置長寬
                      VerifyCode verifyCode = iVerifyCodeGen.generate(80, 28);
                      String code = verifyCode.getCode();
                      LOGGER.info(code);
                      //將VerifyCode綁定session
                      request.getSession().setAttribute("VerifyCode", code);
                      //設置響應頭
                      response.setHeader("Pragma", "no-cache");
                      //設置響應頭
                      response.setHeader("Cache-Control", "no-cache");
                      //在代理服務器端防止緩沖
                      response.setDateHeader("Expires", 0);
                      //設置響應內容類型
                      response.setContentType("image/jpeg");
                      response.getOutputStream().write(verifyCode.getImgBytes());
                      response.getOutputStream().flush();
                  } catch (IOException e) {
                      LOGGER.info("", e);
                  }
              }
          

          搞定!后臺編寫到此結束了。那么又會有博友說了:“說好的實現(xiàn)效果呢?”

          好吧,那么我們繼續(xù)前端的代碼編寫。

          前端代碼:

           <html>
          <body>
          
          <div>
              <input id="code" placeholder="驗證碼" type="text" class=""
                     style="width:170px">
              <!-- 驗證碼 顯示 -->
              <img οnclick="javascript:getvCode()" id="verifyimg" style="margin-left: 20px;"/>
          </div>
          
          <script type="text/javascript">
              getvCode();
          
              /**
               * 獲取驗證碼
               * 將驗證碼寫到login.html頁面的id = verifyimg 的地方
               */
              function getvCode() {
                  document.getElementById("verifyimg").src = timestamp("http://127.0.0.1:81/verifyCode");
              }
              //為url添加時間戳
               function timestamp(url) {
                  var getTimestamp = new Date().getTime();
                  if (url.indexOf("?") > -1) {
                      url = url + "×tamp=" + getTimestamp
                  } else {
                      url = url + "?timestamp=" + getTimestamp
                  }
                  return url;
              };
          
          
          </script>
          </body>
          
          </html>
          

          可以實現(xiàn)點擊圖片更換驗證碼。

          實現(xiàn)效果:

          ?

          當然文章開頭的截圖是我系統(tǒng)中的截圖,需要大家自己去根據(jù)自己的情況去開發(fā)前端了。


          驗證碼是用來防止惡意破解密碼、防止機器登錄的,我們常見的驗證碼形式五花八門,有圖片驗證碼、短信驗證碼、語音驗證碼、拼圖驗證、找圖驗證、點字驗證還有智能檢測,今天我來跟大家分享的是普通的圖片驗證碼。

          12306驗證碼

          網(wǎng)友惡搞的驗證碼

          QQ驗證碼

          生成驗證碼

          ThinkPHP內置了Verify類,生成驗證碼僅需兩步:

          生成驗證碼代碼

          然后在index.html中使用img標簽顯示驗證碼:

          <img src="{:U('Index/verifyCode')}">

          最終輸出結果如下:

          驗證碼顯示結果

          配置驗證碼

          上面的用法是通過默認配置來輸出的驗證碼,5位字母、添加混淆線、添加雜點、字體隨機、顏色隨機,如果這種驗證碼已經可以滿足你的要求,直接使用即可,如果無法滿足要求,可以通過下面的配置來自定義驗證碼:

          圖片來自ThinkPHP官方文檔

          驗證碼字體

          默認情況下,驗證碼的字體是隨機使用 ThinkPHP/Library/Think/Verify/ttfs/目錄下面的字體文件,我們可以指定驗證碼的字體,例如:

          $Verify = new \Think\Verify();

          // 驗證碼字體使用 ThinkPHP/Library/Think/Verify/ttfs/5.ttf

          $Verify->fontttf = '5.ttf';

          $Verify->entry();

          背景圖片

          $Verify = new \Think\Verify();

          // 開啟驗證碼背景圖片功能 隨機使用 ThinkPHP/Library/Think/Verify/bgs 目錄下面的圖片

          $Verify->useImgBg = true;

          $Verify->entry();

          中文驗證碼

          如果要使用中文驗證碼,可以設置:

          $Verify = new \Think\Verify();

          $Verify->useZh = true;

          $Verify->entry();

          指定驗證碼字符

          3.2.1版本以上,我們可以指定驗證碼的字符,通過重新設置codeSet參數(shù)即可,例如設置純數(shù)字驗證碼:

          $Verify = new \Think\Verify();

          $Verify->codeSet = '0123456789';

          $Verify->entry();

          部分中文字符驗證碼:

          $Verify = new \Think\Verify();

          $Verify->useZh = true;

          $Verify->zhSet = '們以我到他會作時要動國產的一是工就年階義發(fā)成部民可出能方進在了不和有大這';

          $Verify->entry();

          驗證碼檢測

          設置了驗證碼,我們應該怎么檢測用戶輸入是否正確呢?只需要使用Verify類下的check方法即可:

          $verify = new \Think\Verify();

          return $verify->check($code);

          多個驗證碼

          如果在同一個頁面中包含多個驗證碼,上面的方法會導致后生成的驗證碼覆蓋掉先生成的SESSION,導致驗證失敗,此時我們需要在生成驗證碼代碼中使用id標識,如下:

          $Verify->entry(1);//第一個驗證碼

          $Verify->entry(2);//第二個驗證碼

          在檢測的時候也一樣

          $verify->check($code,1);//檢測第一個驗證碼

          $verify->check($code,2);//檢測第二個驗證碼

          總結

          ThinkPHP內置的驗證碼類基本上可以滿足我們的需求,而且使用簡單,方便快捷,免去我們自己寫驗證碼生成的麻煩。不過圖片驗證碼已經逐步的被替代,如果你感興趣,可以前往極驗驗證(http://www.geetest.com/)了解更神奇的驗證方式(不過是收費的)。

          如果您覺得小編的教程對您有所幫助,請點擊關注支持小編,您的關注是對小編最大的鼓勵。


          主站蜘蛛池模板: 国产天堂在线一区二区三区 | 69福利视频一区二区| 日本免费一区二区三区最新| 国产激情一区二区三区小说| 亚洲色偷精品一区二区三区| 国产精品一区二区在线观看| 久久精品国产一区二区| 久久国产免费一区二区三区 | 亚洲AV无码国产精品永久一区| 精品人妻无码一区二区色欲产成人| 国产一区二区三区播放心情潘金莲 | 精品亚洲A∨无码一区二区三区| 精品动漫一区二区无遮挡| 国产剧情一区二区| 久久国产一区二区| 无码一区二区三区在线| 国产精品亚洲综合一区| 极品尤物一区二区三区| 亚洲片一区二区三区| 一区二区三区福利视频免费观看| 亚洲日韩一区二区三区| 黄桃AV无码免费一区二区三区| 亚洲一区电影在线观看| 精品一区二区三区免费视频| 国产成人精品第一区二区| 上原亚衣一区二区在线观看| 亚洲高清日韩精品第一区| 久久久久人妻一区精品| 中文字幕无码不卡一区二区三区| 国产成人久久精品麻豆一区| 亚洲电影国产一区| 精彩视频一区二区| 国产一区二区三区免费视频| 美女视频一区三区网站在线观看| 国产一国产一区秋霞在线观看| 亚洲av无码一区二区三区不卡| 精品国产日韩亚洲一区91| 精品无码日韩一区二区三区不卡 | 中文字幕人妻AV一区二区| 中文字幕在线观看一区二区三区| 国产成人欧美一区二区三区|