Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 高清不卡免费一区二区三区,久久精品成人国产午夜,亚洲国产一成人久久精品

          整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          php實現簡易驗證碼(僅供初學者測試玩玩)

          php結合html怎么實現驗證碼,這可能是很多人想知道的,尤其是php初學者。其實想要實現驗證碼的方式有很多種,但是對于初學者來說,有得可能過于復雜不適合新手。這里提供一個很簡易的,僅供初學者試玩,不要覺得瞧不起,再復雜的技術也是從一些簡單的代碼延伸出來的。

          1、首先新建一個php文件,輸入html基本模板,然后將下面這段php代碼插入body里:

          這段代碼首先聲明了編碼格式UTF-8,其次定義了一個空字符,接著通過字符串連接功能和mt_rand()隨機函數,生成四個顏色隨機的隨機數。

          2、接下來就要寫html代碼

          這里要說一下:做一個隱藏的div保存生成的驗證碼,后面可以用來跟用戶輸入的進行比對。

          3、js驗證

          點擊提交按鈕,獲取到隱藏div里的文本值和輸入框的值,進行比較,判斷值是否一致,從而判斷驗證成功與否。

          當然這只是給新手練手,提供一個思路用的。真正做網站驗證碼比這個復雜多,要考慮很多安全因素。

          天星期三了,如果不發生什么不可抗力事件,再過兩天就放假了。

          倒計時兩天

          不過不要高興太早,三天后就是年度最大電商節了,錢包是不是又要瘦身了。

          me too

          話說小編這兩天在忙著給項目做登錄界面,涉及到驗證碼,找了一下,發現現在網上大部分驗證碼都是后臺生成圖片,在前臺顯示,驗證也是在后臺驗證。小編就在想,只用前端技術能不能做出驗證碼呢?經過一番努力,終于做出來了,先看大家一下效果圖

          感覺看著和圖片沒差

          下面給大家一步一步講解代碼:

          HTML代碼:

          <table>

          <tr>

          <td style="width: 70px;height: 40px;"><span >驗證碼:</span></td>

          /* 輸入框*/

          <td><input id="Text3" type="text" class="txtCode"/></td>

          /* 畫布,用來顯示驗證碼 */

          <td><canvas id="canvas" width="120" height="40"></canvas></td>

          </tr>

          </table>

          <script>

          document.getElementById("Text3").addEventListener("change",defined);

          //給輸入驗證碼的input添加監聽事件,當輸入框的值改變的時候,觸發defined()函數。

          var code = " ";

          function defined() {

          var text = document.getElementById("Text3").value.toUpperCase();

          //獲取輸入框的值,并用toUpperCase()將其轉化為大寫。

          function clearAndUpdate() {

          //定義clearAndUpdate()函數。用于在驗證碼錯誤的情況下刷新驗證碼和清空輸入框的值。

          document.getElementById("Text3").value = '';

          //清空輸入框的值。

          drawPic();

          調用drawPic(),刷新驗證碼。

          }

          //對驗證碼進行驗證。

          if(text.length < 0){//判斷為空的情況,彈出提示框。

          alert("請輸入驗證碼");

          }else if(text.length !==4){//判斷驗證碼位數不等于4的情況。

          alert("請輸入正確格式的驗證碼");

          clearAndUpdate();

          }else if(text == code){//比較驗證碼

          alert("通過驗證");

          }else{

          alert("驗證碼錯誤");//其他情況

          clearAndUpdate();

          }

          }

          下面是生成驗證碼的代碼,是利用畫布生成類似圖片的驗證碼。

          //生成一個隨機數

          function randomNum(min,max){

          return Math.floor( Math.random()*(max-min)+min);//在max和min之間生成隨機數。

          }

          //生成一個隨機色

          function randomColor(min,max){//采用rgb顏色,注意顏色是0-255。

          var r = randomNum(min,max);

          var g = randomNum(min,max);

          var b = randomNum(min,max);

          return "rgb("+r+","+g+","+b+")";

          }

          drawPic();

          //點擊驗證碼,則刷新驗證碼

          document.getElementById("canvas").onclick = function(e){

          e.preventDefault();

          drawPic();

          };

          //繪制驗證碼圖片

          function drawPic(){

          var canvas=document.getElementById("canvas");//獲取畫布容器

          var width=canvas.width;//分別獲取畫布的寬和高。

          var height=canvas.height;

          var ctx = canvas.getContext('2d');//獲取該canvas的2D繪圖環境對象

          ctx.textBaseline = 'bottom';設置文本基線是畫布的底部。

          //繪制背景色

          ctx.fillStyle = randomColor(200,240); //顏色若太深可能導致看不清

          ctx.fillRect(0,0,width,height);//畫出矩形,要記得ctx.fillStyle放在ctx.fillRect哦。

          //繪制文字

          var str = 'ABCEFGHJKLMNPQRSTWXY123456789';//選擇全部大寫字母和數字,這下知道為啥要把獲取的值轉化為大寫了吧。

          code = "";//定義一個變量code用于存儲生成的驗證碼。

          for(var i=0; i<4; i++){//這里i<4是生成4位數的驗證碼。

          var txt = str[randomNum(0,str.length)];//隨機獲取str的一個元素。

          code += txt;//將元素加入到code里。

          ctx.fillStyle = randomColor(50,160); //隨機生成字體顏色

          ctx.font = randomNum(15,30)+'px SimHei'; //隨機生成字體大小

          var x = 10+i*25;//元素在水平方向上的位置。

          var y = randomNum(25,35);//元素在豎直方向上的位置,盡量保持在中間,防止部分元素在畫布外。

          var deg = randomNum(-45, 45);//隨機生成旋轉角度。

          //修改坐標原點和旋轉角度

          ctx.translate(x,y);//平移元素

          ctx.rotate(deg*Math.PI/180);//旋轉元素

          ctx.fillText(txt, 0,0);

          //恢復坐標原點和旋轉角度

          ctx.rotate(-deg*Math.PI/180);

          ctx.translate(-x,-y);

          }

          //繪制干擾線

          for(var i=0; i<2; i++){

          ctx.strokeStyle = randomColor(40,180);//干擾線顏色。

          ctx.beginPath();//開始繪制。

          ctx.moveTo( randomNum(0,width), randomNum(0,height) );//起點位置

          ctx.lineTo( randomNum(0,width), randomNum(0,height) );//終點位置

          ctx.stroke();

          }

          /**繪制干擾點**/

          for(var i=0; i<50; i++){

          ctx.fillStyle = randomColor(0,255);

          ctx.beginPath();

          ctx.arc(randomNum(0,width),randomNum(0,height), 1, 0, 2*Math.PI);繪制點,下面說arc函數。

          ctx.fill();

          }

          }

          </script>

          arc() 方法創建弧/曲線

          context.arc(x,y,r,sAngle,eAngle,counterclockwise);

          x圓的中心的 x 坐標。

          y圓的中心的 y 坐標。

          r圓的半徑。

          sAngle起始角,以弧度計。(弧的圓形的三點鐘位置是 0 度)。

          eAngle結束角,以弧度計。

          counterclockwise可選。規定應該逆時針還是順時針繪圖。False = 順時針,true = 逆時針。

          這就是全部的代碼了。

          在頁面上試一下,首先是隨機生成的驗證碼,

          開始輸入不是4位數的驗證碼,點擊確定后會刷新驗證碼。

          然后是4位數,但是不正確的驗證碼,

          當我們輸入正確的驗證碼時,

          這就是我做的驗證碼功能了,都是原生的js,沒有用后臺的知識,小伙伴有沒有理解哦。

          最近因為項目快要交付了,所有人都開始動員起來測試系統,因為小編參與了整個的開發流程,所以很多同事遇到bug都來問我,需要在哪里改,東西寫在哪了。第一次知道改bug這么費精力,改了這個,又出來好幾個新的,簡直爆炸。

          打死也不承認是我寫的

          不說了,一會經理要問我改多少bug了。

          不敢跑,不敢跑

          AJ-Captcha行為驗證碼,包含滑動拼圖、文字點選兩種方式,UI支持彈出和嵌入兩種方式。后端提供Java實現,前端提供了php、angular、html、vue、uni-app、flutter、android、ios等代碼示例。


          源碼倉庫以及協議

          源碼地址:https://gitee.com/anji-plus/captcha

          基于apache2協議,開源免費商用,但需要保留版權聲明

          Apache 2.0 開源協議具有以下特點:

          1. 授權:該協議允許任何人自由使用、復制、修改、分發和銷售被許可軟件的副本。

          2. 版權聲明:被許可軟件的副本必須包含原始版權聲明和許可聲明。

          3. 專利授權:該協議授予了對軟件相關專利的非專屬授權,這意味著使用該軟件的人不會受到專利侵權的指控。

          4. 責任限制:被許可軟件是按"原樣"提供的,沒有任何明示或暗示的擔保和條件。使用者對軟件的使用有責任承擔風險。

          5. 分發修改版本:使用者可以基于被許可軟件創建衍生作品,并將其分發。然而,衍生作品必須遵循Apache 2.0協議,并包含相應的版權聲明和許可聲明。

          總體而言,Apache 2.0 開源協議提供了靈活的許可方式,鼓勵創新和共享。它廣泛應用于許多開源軟件項目,包括Apache HTTP服務器等。

          項目啟動

          • 后端工程

          提供了go、php、java(springboot、springmvc)多種版本,我們這里以springboot為例

          直接運行 StartApplication.java,配置文件先不修改 ,使用默認的,我們一會兒再來看看都有些什么配置項

          • 前端

          提供的版本有很多,我們這里以vue為例演示

          本地啟動執行命令,記得修改接口地址

          npm install
          npm run dev

          啟動成功后可以看到演示界面

          功能體驗

          進入內部頁面后,還有前端代碼集成示例,可以非常方便的集成到自己的項目中去

          技術細節

          • 整體時序圖

          整體時序圖

          • 后端的配置項

          captcha/service/springboot/src/resources/application.properties

          spring.application.name=captcha-service
          server.port=8080
          
          # 滑動驗證,底圖路徑,不配置將使用默認圖片
          # 支持全路徑
          # 支持項目路徑,以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
          
          # 對于分布式部署的應用,我們建議應用自己實現CaptchaCacheService,比如用Redis或者memcache,
          # 參考CaptchaCacheServiceRedisImpl.java
          # 如果應用是單點的,也沒有使用redis,那默認使用內存。
          # 內存緩存只適合單節點部署的應用,否則驗證碼生產與驗證在節點之間信息同步,導致失敗。
          # !!! 注意啦,如果應用有使用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代表不執行
          #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
          # 漢字統一使用Unicode,保證程序通過@value讀取到是中文,可通過這個在線轉換
          # https://tool.chinaz.com/tools/unicode.aspx 中文轉Unicode
          # 右下角水印文字(我的水印)
          aj.captcha.water-mark=我的水印
          # 右下角水印字體(不配置時,默認使用文泉驛正黑)
          # 由于宋體等涉及到版權,我們jar中內置了開源字體【文泉驛正黑】
          # 方式一:直接配置OS層的現有的字體名稱,比如:宋體
          # 方式二:自定義特定字體,請將字體放到工程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
          
          #點選字體樣式 默認Font.BOLD
          aj.captcha.font-style=1
          #點選字體字體大小
          aj.captcha.font-size=25
          #點選文字個數,存在問題,暫不支持修改
          #aj.captcha.click-word-count=4
          
          
          aj.captcha.history-data-clear-enable=false
          
          # 接口請求次數一分鐘限制是否開啟 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接口一分鐘內請求數限制
          aj.captcha.req-get-minute-limit=30
          # check接口一分鐘內請求數限制
          aj.captcha.req-check-minute-limit=30
          # verify接口一分鐘內請求數限制(暫用不上,可后臺直接調用captchaService)
          #aj.captcha.req-verify-minute-limit=30
          

          可以看到后端可以配置的選項還是很多的,可以切換緩存類型,展示底圖,接口限制等等

          • 接口分析

          我們嘗試滑動一次,發現在整個請求過程中,前端向后端發出了2個接口請求

          第1個是滑動停止時,帶著滑動碼類型和位置信息請求check校驗接口,如果滑動得是正確得位置,則里面得result字段為ture

          http://localhost:8080/captcha/check
          
          {"captchaType":"blockPuzzle","pointJson":"Ld/yNtPlENUtOoX2qdKHvNO5y/X8LU+vOUPWfitmrjc=","token":"3d5591a033d8482c89e0a77f477a9365"}
          
          {
          "repCode": "0000",
          "repMsg": null,
          "repData": {
          "captchaId": null,
          "projectCode": null,
          "captchaType": "blockPuzzle",
          "captchaOriginalPath": null,
          "captchaFontType": null,
          "captchaFontSize": null,
          "secretKey": null,
          "originalImageBase64": null,
          "point": null,
          "jigsawImageBase64": null,
          "wordList": null,
          "pointList": null,
          "pointJson": "Ld/yNtPlENUtOoX2qdKHvNO5y/X8LU+vOUPWfitmrjc=",
          "token": "3d5591a033d8482c89e0a77f477a9365",
          "result": true,
          "captchaVerification": null,
          "clientUid": null,
          "ts": null,
          "browserInfo": null
          },
          "success": true
          }

          第2個其實是獲取圖片驗證碼得請求,是因為第一個我們滑動到了正確位置,所以界面刷新又獲取了一次新得圖片驗證碼

          http://localhost:8080/captcha/get

          實際上真正做滑動校驗得是/check 這個接口

          src/main/java/com/anji/captcha/service/impl/BlockPuzzleCaptchaServiceImpl.java

          public ResponseModel check(CaptchaVO captchaVO) {
          		ResponseModel r = super.check(captchaVO);
          		if(!validatedReq(r)){
          			return r;
          		}
                  //取坐標信息
                  String codeKey = String.format(REDIS_CAPTCHA_KEY, captchaVO.getToken());
                  if (!CaptchaServiceFactory.getCache(cacheType).exists(codeKey)) {
                      return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_INVALID);
                  }
                  String s = CaptchaServiceFactory.getCache(cacheType).get(codeKey);
                  //驗證碼只用一次,即刻失效
                  CaptchaServiceFactory.getCache(cacheType).delete(codeKey);
                  PointVO point = null;
                  PointVO point1 = null;
                  String pointJson = null;
                  try {
                      point = JsonUtil.parseObject(s, PointVO.class);
                      //aes解密
                      pointJson = decrypt(captchaVO.getPointJson(), point.getSecretKey());
                      point1 = JsonUtil.parseObject(pointJson, PointVO.class);
                  } catch (Exception e) {
                      logger.error("驗證碼坐標解析失敗", e);
                      afterValidateFail(captchaVO);
                      return ResponseModel.errorMsg(e.getMessage());
                  }
                  if (point.x - Integer.parseInt(slipOffset) > point1.x
                          || point1.x > point.x + Integer.parseInt(slipOffset)
                          || point.y != point1.y) {
                      afterValidateFail(captchaVO);
                      return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_COORDINATE_ERROR);
                  }
                  //校驗成功,將信息存入緩存
                  String secretKey = point.getSecretKey();
                  String value = null;
                  try {
                      value = AESUtil.aesEncrypt(captchaVO.getToken().concat("---").concat(pointJson), secretKey);
                  } catch (Exception e) {
                      logger.error("AES加密失敗", e);
                      afterValidateFail(captchaVO);
                      return ResponseModel.errorMsg(e.getMessage());
                  }
                  String secondKey = String.format(REDIS_SECOND_CAPTCHA_KEY, value);
                  CaptchaServiceFactory.getCache(cacheType).set(secondKey, captchaVO.getToken(), EXPIRESIN_THREE);
                  captchaVO.setResult(true);
                  captchaVO.resetClientFlag();
                  return ResponseModel.successData(captchaVO);
              }
          

          分析一下接口的實現,經過了坐標解密(滑塊圖的坐標信息是通過加密后傳輸給前端),坐標對比,需要滑動的位置在允許的范圍內才認為滑動位置正確

          再來看看驗證碼生成的實現

          src/main/java/com/anji/captcha/service/impl/BlockPuzzleCaptchaServiceImpl.java

          public ResponseModel get(CaptchaVO captchaVO) {
          		ResponseModel r = super.get(captchaVO);
          		if(!validatedReq(r)){
          			return r;
          		}
                  //原生圖片
                  BufferedImage originalImage = ImageUtils.getOriginal();
                  if (null == originalImage) {
                      logger.error("滑動底圖未初始化成功,請檢查路徑");
                      return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_BASEMAP_NULL);
                  }
                  //設置水印
                  Graphics backgroundGraphics = originalImage.getGraphics();
                  int width = originalImage.getWidth();
                  int height = originalImage.getHeight();
                  backgroundGraphics.setFont(waterMarkFont);
                  backgroundGraphics.setColor(Color.white);
                  backgroundGraphics.drawString(waterMark, width - getEnOrChLength(waterMark), height - (HAN_ZI_SIZE / 2) + 7);
          
                  //摳圖圖片
                  String jigsawImageBase64 = ImageUtils.getslidingBlock();
                  BufferedImage jigsawImage = ImageUtils.getBase64StrToImage(jigsawImageBase64);
                  if (null == jigsawImage) {
                      logger.error("滑動底圖未初始化成功,請檢查路徑");
                      return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_BASEMAP_NULL);
                  }
                  CaptchaVO captcha = pictureTemplatesCut(originalImage, jigsawImage, jigsawImageBase64);
                  if (captcha == null
                          || StringUtils.isBlank(captcha.getJigsawImageBase64())
                          || StringUtils.isBlank(captcha.getOriginalImageBase64())) {
                      return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_ERROR);
                  }
                  return ResponseModel.successData(captcha);
              }

          大致過程:加載驗證碼底圖、隨機從底圖中扣取一個部分作為要滑動的小圖,最后把兩個圖都以base64圖片形式返回給前端

          總結

          1、本篇我們介紹了一個開源免費的行為驗證碼的項目

          2、完成了項目的實際搭建和功能體驗

          3、我們初步分析了后端的核心代碼,了解了滑動驗證碼的生成和校驗邏輯

          4、整體來說這個項目非常完整,并且提供了很多的終端實現(常見的基本上都支持了,html,vue,小程序終端,原生ios android等),并且后端也是非常容易集成到自己的項目,拿著demo版本修改一下即可


          主站蜘蛛池模板: 亚洲av乱码中文一区二区三区| 精品一区二区三区高清免费观看| 国产美女一区二区三区| 亚洲午夜精品一区二区公牛电影院 | 国产精品免费视频一区| 亚洲国产精品一区| 狠狠色成人一区二区三区| 日本精品一区二区在线播放| 日韩精品乱码AV一区二区| 丝袜人妻一区二区三区网站| 午夜精品一区二区三区在线视| 曰韩人妻无码一区二区三区综合部| 午夜福利一区二区三区高清视频| 中文字幕日韩一区二区三区不 | 91一区二区三区| 乱人伦一区二区三区| 国产一区中文字幕| 欧美激情一区二区三区成人| 国产福利一区二区三区在线观看| 亚洲一区二区三区夜色| 国产高清不卡一区二区| 免费日本一区二区| 国模吧一区二区三区| 久久精品国产免费一区| 无码人妻AⅤ一区二区三区| 国产成人久久精品一区二区三区 | 最新欧美精品一区二区三区| 激情内射亚洲一区二区三区| 中文字幕一区二区三区精彩视频| 无码人妻精品一区二区三18禁| 亚洲av乱码一区二区三区香蕉| 日本国产一区二区三区在线观看 | 亚洲性日韩精品国产一区二区| 日本精品一区二区三本中文| 一区三区三区不卡| 国产日韩AV免费无码一区二区| 色婷婷一区二区三区四区成人网| 国产高清一区二区三区| 午夜DV内射一区区| 激情内射日本一区二区三区| 亚洲一区二区在线视频|