這篇文章給大家分享的是API 交互實(shí)現(xiàn)圖片驗(yàn)證碼的詳細(xì)介紹,相信大部分人都還沒(méi)學(xué)會(huì)這個(gè)技能,為了讓大家更加了解,給大家總結(jié)了以下內(nèi)容,話不多說(shuō),一起往下看吧。
創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),蘇尼特左企業(yè)網(wǎng)站建設(shè),蘇尼特左品牌網(wǎng)站建設(shè),網(wǎng)站定制,蘇尼特左網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷,網(wǎng)絡(luò)優(yōu)化,蘇尼特左網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。
在傳統(tǒng)的 Web 開發(fā)過(guò)程中,處理圖形驗(yàn)證碼很簡(jiǎn)單,只需要在后臺(tái)用隨機(jī)字符串生成一個(gè)圖片,將驗(yàn)證碼內(nèi)容放進(jìn) Session 即可,用戶提交表單時(shí)從 Session[1] 取出判斷即可。
但是現(xiàn)如今,越來(lái)越推崇 API 交互,無(wú)狀態(tài),在 Session 這一塊,雖然默認(rèn)配置是不支持了,但是還是有很多曲線救國(guó)的方法。
在 API 開發(fā)中,我們也可以給前端簽發(fā) SessionID ,并且通過(guò) PHP 的內(nèi)置方法,來(lái)實(shí)現(xiàn)這一切。
比如 我們與前段約定,當(dāng)在請(qǐng)求中包含有 X-Session-Id
,且不為空時(shí),表示這個(gè)會(huì)話已經(jīng)注冊(cè)過(guò) SessionID ,否則就頒布一個(gè) SessionID 并返回在 Response Header 中的 X-Session-Id
讓前段記錄這個(gè) SessionID ,下面簡(jiǎn)單實(shí)現(xiàn)一下。
// code_session.php session_start(); // 這里假設(shè)已經(jīng)通過(guò) Header 獲取到了 SessionID,并保存到了 $sessionId 變量中。 // 當(dāng) SessionID 不存在,或者 為空 則創(chuàng)建新的 SessionID 。 if(!isset($sessionId) || empty($sessionId)){ $sessionId = session_create_id(); // 因?yàn)榍芭_(tái)還沒(méi)有 SessionID ,所以下發(fā)一個(gè),通知前端保存。 header('X-Session-Id: '.$sessionId); } // 設(shè)置當(dāng)前會(huì)話的 SessionID 。 session_id($sessionId); // 這里我們就可以自由的讀寫 Session 了。 // 生成驗(yàn)證碼 $code = mt_rand(1e3 ,1e4-1); // create_image 請(qǐng)自行實(shí)現(xiàn) 或者使用現(xiàn)有的圖形驗(yàn)證碼庫(kù)生成。 $image = create_image($code); // 存儲(chǔ)進(jìn)去 Session $_SESSION['code'] = $code; // 輸出一張圖片 $image->output();
上面基本實(shí)現(xiàn)了生成圖片,前端需要根據(jù) 只需要再提交表單時(shí),在 headers 中帶上 X-Session-ID
即可。
// code_session_validate.php session_start(); // 這里假設(shè)已經(jīng)通過(guò) Header 獲取到了 SessionID,并保存到了 $sessionId 變量中。 // 當(dāng) SessionID 不存在,或者 為空 則創(chuàng)建新的 SessionID 。 if( !isset($sessionId) || empty($sessionId) || !isset($_POST['code']) || empty($_POST['code']) ){ // 因?yàn)闆](méi)有提交 SessionID 過(guò)來(lái) 這個(gè)肯定就是不成立的了,所以直接終止即可。 exit; } // 設(shè)置當(dāng)前會(huì)話的 SessionID 。 session_id($sessionId); if($_POST['code']!=$_SESSION['code']){ // 驗(yàn)證碼錯(cuò)誤啦 exit; } // 驗(yàn)證通過(guò)了就刪掉 code, unset($_SESSION['code']);
上面使用 Session ,我們基本就實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的驗(yàn)證,而且是基于 API 交互的,不依賴瀏覽器 cookie 。當(dāng)我們需要一些復(fù)雜的比如共享 Session ,這些就不在本文的討論范圍了(其實(shí)現(xiàn)在也已經(jīng)超綱了)
接下來(lái)的方法是無(wú)狀態(tài)的,但是需要用到 redis 。這里使用 PHPRedis 這個(gè)擴(kuò)展來(lái)處理。
在大多數(shù)情況下,我們并不需要像上面使用 Session 那樣來(lái)創(chuàng)建過(guò)多的 Session ,造成有一些資源浪費(fèi),當(dāng)然,Session 可以做的不止這些,下面我們就用 Redis 來(lái)做一個(gè)客戶端主動(dòng)簽發(fā)
的圖片驗(yàn)證碼。
由客戶端本地生成隨機(jī)字符串,然后拼接在獲取驗(yàn)證碼地址的后面,后端截取客戶端生成的隨機(jī)字符串,用此作為驗(yàn)證憑證放入 Redis 中去,再客戶端提交時(shí)需要帶上先前生成的隨機(jī)字符串一同進(jìn)項(xiàng)驗(yàn)證。
// code_client.php $salt = 'wertyujkdbaskndasda'; if(!isset($_GET['sign'])){ // 客戶端沒(méi)有提供簽名,停止執(zhí)行 exit; } // 用戶傳來(lái)的一切數(shù)據(jù)都是不可靠的,我們需要對(duì)其加鹽后執(zhí)行 md5 $sign = md5($_GET['sign'].$salt); // 拼接上簽名作為 Redis 的 key $key = 'code:'.$sign; // 連接 Redis $cache = new \Redis(); // 生成驗(yàn)證碼 $code = mt_rand(1e3,1e4-1); // 保存驗(yàn)證碼到 Redis 并設(shè)置2分鐘的有效期。 if($cache->exists($key)){ // 這個(gè) Key 已經(jīng)被占用了,這里先停止。 exit; } $cache->set($key,$code,60*2); // 創(chuàng)建圖片并返回 $image = create_image($code); $image->output();
好了,接下來(lái)驗(yàn)證一下。
// code_client_validate.php $salt = 'wertyujkdbaskndasda'; if( !isset($_POST['sign']) || !isset($_POST['code']) // 沒(méi)有提交驗(yàn)證碼過(guò)來(lái)。 || !empty($_POST['code']) ){ // 客戶端沒(méi)有提供簽名,停止執(zhí)行 exit; } // 用戶傳來(lái)的一切數(shù)據(jù)都是不可靠的,我們需要對(duì)其加鹽后執(zhí)行 md5 $sign = md5($_POST['sign'].$salt); // 拼接上簽名作為 Redis 的 key $key = 'code:'.$sign; // 連接 Redis $cache = new \Redis(); if(!$cache->exists($key)){ // 根本沒(méi)有這個(gè) key eixt; } if($cache->get($key)!=$_POST['code']){ // 驗(yàn)證碼錯(cuò)誤 } // 驗(yàn)證通過(guò)了就刪除 $cache->del($key);
看著是不是要復(fù)雜點(diǎn)兒,甚至還用上了 Redis ,雖然看著不咋地,但是他也實(shí)現(xiàn)了我們想要的,不過(guò)這個(gè)也不算是太好的方案,而且,還要考慮客戶端字符串不夠隨機(jī)的情況,接下來(lái)我們改變一下方向,換成服務(wù)端簽發(fā)。
剛剛的是基于客戶端簽發(fā)的實(shí)現(xiàn),下面來(lái)提供另一種思路,但是大體上,這個(gè)是差不多的哈都。
同樣是簽發(fā) Sign ,只不過(guò)這次由服務(wù)端來(lái)簽發(fā),然后將 Sign 通過(guò) Header 發(fā)送給客戶端,客戶端需要先取到圖片資源,注意這里返回的應(yīng)該是一個(gè)合法的二進(jìn)制流,然后從 header 中取出 Sign ,同時(shí)展示給用戶。
// code_server.php $cache = new \Redis(); $salt = 'wertyujkdbaskndasda'; function generateSign(){ global $cache,$salt; $sign = md5(mt_rand().$salt); // 拼接上簽名作為 Redis 的 key $key = 'code:'.$sign; if($cache->exists($key)){ // 是的 你么有看錯(cuò),就是如果生成的 Sign 已存在,就進(jìn)行遞歸,直到生成出一個(gè)不存在的。 return generateSign(); } return $key; } // 連接 Redis $key = generateSign(); // 生成驗(yàn)證碼 $code = mt_rand(1e3,1e4-1); // 保存驗(yàn)證碼到 Redis 并設(shè)置2分鐘的有效期。 $cache->set($key,$code,60*2); // 創(chuàng)建圖片并返回 $image = create_image($code); // 哈哈 要剃掉前綴喲 header('X-Captcha-Sign: ' . str_replace('code:','',$key)); $image->output();
看起來(lái)幾乎沒(méi)有變化,只是生成 Sign 的方式變了一下,但是,這樣搞的話,前端同學(xué)可能就不爽了,他們要先獲取這個(gè)資源和 headers 中的 X-Captcha-Sign
再 show 到界面上,當(dāng)然 可以直接將結(jié)果 base64 或者 直接用用二進(jìn)制流生成位圖顯示都是可以的,我們只是需要可以驗(yàn)證,驗(yàn)證方法直接使用上面的即可。
當(dāng)你使用 ajax 獲取這個(gè)資源是,如果你的業(yè)務(wù)涉及到了跨域,你還需要在響應(yīng)頭設(shè)置 Access-Control-Expose-Headers - HTTP | MDN,否則 ajax 無(wú)法獲取自定義的響應(yīng)頭。。
header('Access-Control-Expose-Headers: X-Captcha-Sign');
看了這三種解決方案,基本都能滿足我們的需求,可能還有人想到了另一種方案。提供一個(gè) json 接口名,在后臺(tái)生成圖片然后保存起來(lái),返回 url 和 sign 給前端,這樣就好了,但是這樣做,我們的資源并不太可控,會(huì)造成一定的資源浪費(fèi),這里我并沒(méi)有考慮 這種方案。
文中所提到的一些知識(shí)都是對(duì)一些基礎(chǔ)知識(shí)的應(yīng)用,文章中的代碼是寫文章直接敲的,如果有排版錯(cuò)誤或者邏輯錯(cuò)誤,請(qǐng)不吝賜教。
文中所用到的 Redis 為 PHPRedis 擴(kuò)展。至于驗(yàn)證碼圖片生成可以用 gregwar/captcha - Packagist 來(lái)做。
看完上述內(nèi)容,你們對(duì)API 交互實(shí)現(xiàn)圖片驗(yàn)證碼大概了解了嗎?如果想了解更多相關(guān)文章內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!
本文標(biāo)題:API交互實(shí)現(xiàn)圖片驗(yàn)證碼
URL標(biāo)題:http://bm7419.com/article0/igcgoo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁(yè)設(shè)計(jì)公司、靜態(tài)網(wǎng)站、網(wǎng)站營(yíng)銷、網(wǎng)站排名、云服務(wù)器、做網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)