做網(wǎng)絡(luò)爬蟲的同學(xué)肯定見過各種各樣的驗證碼,比較高級的有滑動、點選等樣式,看起來好像挺復(fù)雜的,但實際上它們的核心原理還是還是很清晰的,本文章大致說明下這些驗證碼的原理以及帶大家實現(xiàn)一個滑動驗證碼。
我之前做過 Web 相關(guān)開發(fā),嘗試對接過 Lavavel 的極驗驗證,當(dāng)時還開發(fā)了一個 Lavavel 包:https://github.com/Germey/LaravelGeetest,在開發(fā)包的過程中了解到了驗證碼的兩步校驗規(guī)則。
實際上這類驗證碼的校驗是分為兩個步驟的:
1.第一步就是前端的校驗。一般來說,登錄注冊頁面在點擊提交的時候都會伴隨著一個表單提交,在表單提交的時候會有 JavaScript 事件的觸發(fā)。如果加入了驗證碼,那么在表單提交的時候會多加一個額外的驗證,判斷這個驗證碼是否已經(jīng)成功完成了操作。如果沒有的話,那就直接取消表單的提交,然后順便提示說”您的驗證沒通過,請重新驗證“,諸如此類的話。所以這一步就能防范”君子“之為了。
2.第二步就是服務(wù)端的校驗。意思就是說表單提交之后,會有請求發(fā)送到服務(wù)器,這個請求中包含了很多數(shù)據(jù),比如用戶名、密碼,如果對接了驗證碼的話,還會有額外的驗證碼的值,或者更復(fù)雜的加密后的 Token 值,服務(wù)器會對發(fā)過來的信息進(jìn)行校驗,如果驗證通過,那么整個請求就成功了,返回正常的響應(yīng),否則返回錯誤的響應(yīng)。所以如果想要通過程序來直接構(gòu)造表單提交的時候,服務(wù)端就可以做進(jìn)一步的校驗,由于提交的驗證碼相關(guān)的信息都是和服務(wù)端的 Session 相關(guān)聯(lián)的,另外再加上一些 CSRF 等的校驗,所以這一步就能防范”小人“之為了。
上面就是驗證碼校驗的兩個階段,一般來說為了安全性,在開發(fā)一個網(wǎng)站時需要客戶端和服務(wù)端都加上校驗,這樣才能保證安全性。
本文章主要來介紹一下第一個階段,也就是前端校驗的驗證碼的實現(xiàn),下面來介紹一下拖動驗證碼的具體實現(xiàn)。
需求
那么前端完成一個合格的驗證碼,究竟需要做成什么樣子呢?
1.首先驗證碼有個大體的雛形,既然是拖動驗證碼,那就要拖動塊和目標(biāo)塊,我們需要把拖動塊拖動到目標(biāo)塊上就算校驗成功。
2.驗證碼的一個功能就是來規(guī)避機器的自動操作,所以我們需要通過軌跡來判斷這個拖動過程是真實的人還是機器,因此我們需要記錄拖動的路徑,路徑經(jīng)過計算之后可以發(fā)送到后端進(jìn)行進(jìn)一步的分類,比如對接深度學(xué)習(xí)模型來分類拖動軌跡是否是人。
以上就是驗證碼的兩個基本要求,所以我們這里就來實現(xiàn)一下看看。
結(jié)果
這里就先給大家看看結(jié)果吧:
拖動驗證碼示例
可以看到圖中有一個初始滑塊,有一個目標(biāo)滑塊,如果把初始滑塊拖動到目標(biāo)滑塊上才能校驗成功,然后下方再打印拖動的軌跡,包含它的 x、y 坐標(biāo)。
有了這些內(nèi)容之后,就可以放到表單里面進(jìn)行提交了,軌跡數(shù)據(jù)可以自行加密處理并校驗來判斷其是否合法。
具體實現(xiàn)
下面就具體講解下這個是怎么實現(xiàn)的,實際上核心代碼只有 200 行,下面對整個核心流程進(jìn)行說明。
既然 Vue 這么火,那我這里就用 Vue 來實現(xiàn)啦,具體的環(huán)境配置這里就不再贅述了,需要安裝的有:
Node.js:https://nodejs.org/en/
Vue-Cli:https://cli.vuejs.org/zh/
安裝完成之后便可以使用 vue 命令了,新建個項目:
vuecreatedrag-captcha
然后找一張不錯的風(fēng)景圖,放到 public 目錄下,后面我們會引用它。
另外這里需要一個核心的包叫做 vue-drag-drop,其 GitHub 地址為:https://github.com/cameronhimself/vue-drag-drop,在目錄下使用此命令安裝:
npminstall--savevue-drag-drop
安裝好了之后我們就可以利用它來實現(xiàn)驗證碼了。
首先 vue-drag-drop 提供了兩個組件,一個叫做 Drag,一個叫做 Drop。前者是被拖動對象,后者是放置目標(biāo),我們利用這兩個組件構(gòu)建兩個滑塊,將 Drag 滑塊拖動到 Drop 滑塊上就成功了。因此,我們要做的僅僅是把它們兩個聲明出來并添加幾個檢測方法就好了,至于拖動的功能,vue-drag-drop 這個組件已經(jīng)給我們封裝好了。
這里我們就直接在 App.vue 里面修改內(nèi)容就好了,在里面先聲明一下兩個組件:
很清晰了,一個
Drop
對于 Drop 組件來說,它是一個被放置的對象,被拖動滑塊會放到這個 Drop 滑塊上,這就代表拖動成功了。它有兩個主要的事件需要監(jiān)聽,一個叫做 dragover,一個叫做 dragleave,分別用來監(jiān)聽 Drag 對象拖上和拖開的事件。
在這里,分別對兩個事件設(shè)置了 onDragOver 和 onDragLeave 的回調(diào)函數(shù),當(dāng) Drag 對象放到 Drop 對象上面的時候,就會觸發(fā) onDragOver 對象,當(dāng)拖開的時候就會觸發(fā) onDragLeave 事件。
那這樣的話我們只需要一個全局變量來記錄是否已經(jīng)將滑塊拖動到目標(biāo)位置即可,比如可以定一個全局變量 state,我們用 over 屬性來代表是否拖動到目標(biāo)位置。
因此 onDragOver 和 onDragLeave 事件可以這么實現(xiàn):
onDragOver(){this.state.over=true},onDragLeave(){this.state.over=false}
Drag
對于 Drag 組件來說,它是一個被拖動的對象,我們需要將這個 Drag 滑塊拖動到 Drop 滑塊上,就代表拖動成功了。它有三個主要的時間需要監(jiān)聽:dragstart、drag、dragend,分別代表拖動開始、拖動中、拖動結(jié)束三個事件,我們這里也分別設(shè)置了三個回調(diào)方法 onDragStart、onDrag、onDragEnd。
對于 onDragStart 方法來說,應(yīng)該怎么實現(xiàn)呢?這里應(yīng)該處理剛拖動的一瞬間的動作,由于我們需要記錄拖動的軌跡,所以聲明一個 trace 全局變量來保存軌跡信息,onDragStart 要做的就是初始化 trace 對象為空,另外記錄一下初始的拖動位置,以便后續(xù)計算拖動路徑,所以可以實現(xiàn)如下:
onDragStart(data,event){this.init={x:event.offsetX,y:event.offsetY,}this.trace=[]}
對于 onDrag 方法來說,就是處理拖動過程中的一系列拖動動作,這里其實就是計算當(dāng)前拖動的偏移位置,然后把它保存到 trace 變量里面,所以可以實現(xiàn)如下:
onDrag(data,event){letoffsetX=event.offsetX-this.init.xletoffsetY=event.offsetY-this.init.ythis.trace.push({x:offsetX,y:offsetY,})}
對于 onDragEnd 方法來說,其實就是檢測最后的結(jié)果了,剛才我們用 state 變量里面的 over 屬性來代表是否拖動到目標(biāo)位置上,這里我們也定義了另外的 dragged 屬性來代表是否已經(jīng)拖動完成,dragging 屬性來代表是否正在拖動,所以整個方法的邏輯上是檢測 over 屬性,然后對 dragging、dragged 屬性做賦值,然后做一些相應(yīng)的提示,實現(xiàn)如下:
onDragEnd(){if(this.state.over){this.state.dragging=falsethis.state.dragged=truethis.$message.success('拖動成功')}else{this.state.dragging=falsethis.state.dragged=falsethis.$message.error('拖動失敗')}this.state.over=false}
OK 了,以上便是主要的邏輯實現(xiàn),這樣我們就可以完成拖動滑塊的定義以及拖動的監(jiān)聽了。
接下來就是一些樣式上的問題了,對于圖片的呈現(xiàn),這里直接使用 CSS 的 background-image 樣式來設(shè)置的,如果想顯示圖片的某一個范圍,那就用 background-position 來設(shè)置,這是幾個核心的要點。
好,這里的樣式設(shè)置其實也可以用 JavaScript 來實現(xiàn),我們把它們定義為一些計算屬性:
wrapperStyle(){return{width:this.size.width+'px',height:this.size.height+'px',backgroundImage:'url('+this.image+')',backgroundSize:'cover'}},targetStyle(){return{left:this.block.x+'px',top:this.block.y+'px'}},sourceStyle(){return{backgroundImage:'url('+this.image+')',backgroundSize:this.size.width+'px'+this.size.height+'px',backgroundPosition:-this.block.x+'px'+-this.block.y+'px'}}
另外這里還有一個值得注意的地方,就是 Drag 組件的 slot 部分:
這部分定義了在拖動過程中隨鼠標(biāo)移動的圖片樣式,這里也和 Drag 滑塊一樣定義了一樣的樣式,這樣在拖動的過程中,就會顯示一個和 Drag 滑塊一樣的滑塊隨鼠標(biāo)移動。
最后,就是拖拽完成之后,將滑動軌跡輸出出來,這里我就直接呈現(xiàn)在頁面上了,區(qū)域加入如下定義即可:
拖動軌跡:{{ trace }}
好,以上就是一些核心代碼的介紹,還有一些細(xì)節(jié)的問題可以完善下,比如滑塊隨機初始化位置,以及拖動樣式設(shè)置。
最后再看一遍效果:
拖動驗證碼示例
可以看到我們首先拖動了 Drag 滑塊,當(dāng) Drag 滑塊拖動到 Drop 滑塊上時,出現(xiàn)了白色描邊,證明已經(jīng)拖動到目標(biāo)位置了。然后松手之后,觸發(fā) onDragEnd 方法,呈現(xiàn)拖動軌跡,整個驗證碼就驗證成功了。
當(dāng)然這只是前端部分,如果在這個基礎(chǔ)上添加表單驗證,然后再添加后端校驗,并加上軌跡識別,那可謂是一個完整的驗證碼系統(tǒng)了,在這里就點到為止啦。
最后如果大家想也仿照實現(xiàn)一下的話,可以參考這個組件:
https://github.com/cameronhimself/vue-drag-drop
里面也介紹了其他的一些屬性和事件,在某些情況下還是很有用的。
源代碼:
https://github.com/Germey/DragCaptcha
-
代碼
+關(guān)注
關(guān)注
30文章
4872瀏覽量
69913 -
深度學(xué)習(xí)
+關(guān)注
關(guān)注
73文章
5540瀏覽量
122221 -
驗證碼
+關(guān)注
關(guān)注
2文章
20瀏覽量
4783
原文標(biāo)題:200行代碼實現(xiàn)一個滑動驗證碼
文章出處:【微信號:rgznai100,微信公眾號:rgznai100】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
織夢dedecms登陸提示“驗證碼不正確”的完整解決方案
10種意想不到的驗證碼風(fēng)格設(shè)計
一文解析驗證碼與打碼平臺的攻防對抗
打碼平臺是如何高效的破解市面上各家驗證碼平臺的各種形式驗證碼的?
多樣變換的手寫驗證碼自動識別算法
以一個真實網(wǎng)站的驗證碼為例,實現(xiàn)了基于一下KNN的驗證碼識別
驗證碼層出不窮?試試這個自動跳過驗證碼的工具
驗證碼太麻煩,自動跳過驗證碼神器試一試
爬蟲實現(xiàn)目標(biāo)網(wǎng)站驗證碼登陸
一個短信驗證碼爆破重置
驗證碼到底在驗證啥?聊一聊驗證碼是怎么為難我們?nèi)祟惖?/a>

Java 中驗證碼的使用

SpringBoot分布式驗證碼登錄方案

評論