ThinkPHP5 集成阿里雲滑動驗證功能實例指導
- 2020 年 4 月 3 日
- 筆記
- 背景 最近,項目後台上線後,有人覺得登錄頁的四位驗證碼有時候看不出來,需要刷新好幾次填對;於是在搜索滑動驗證時注意到了阿里雲的這個人機驗證功能;雖然也有好多網友提供實現方法,但是經過自己的操作,覺得自己整理一番,不僅可以幫助新手,也能作為自己以後的經驗備忘,歡迎指摘 …
- 了解概念,不然也找不到自己選擇這個功能的理由吧:
滑動驗證(No-Captcha,簡稱NC)
,是阿里巴巴集團打破傳統驗證碼技術推出的最新人機識別服務。阿里雲的滑動驗證採用先進的風險分析引擎來區分來自人類與機器人的訪問行為。用戶通過類似滑動解鎖的方式來通過人機驗證,對用戶來說無需思考即可通過人機識別(圖靈測試)的挑戰。 - 環境:
框架: ThinkPHP5.1 系統:Nginx、Win10、CentOS7.2
㈠ 前期準備
- 首先,建議閱讀【
人機滑動驗證 官方文檔
】,鄙人覺得裡面介紹的很詳細,作為指導博文,不可能全給摘過來的 - 既然考慮到使用人家的服務,當然得了解一下是不是免費啥的唄,0.002元/條,好在也是不貴吧?
- 【
創建 AccessKey (指導)
】,請使用子帳號(RAM用戶)AccessKey,並為子帳號授予雲盾人機驗證許可權(AliyunYundunAFSFullAccess) - 根據 【
滑動驗證 —— 快速入門
】,在【雲盾人機驗證控制台
】開通、配置
㈡ 前端接入程式碼集成
首先,給出官方文檔介紹【 滑動驗證前端程式碼集成文檔-PCWEB版
】,然後對比我的實際操作程式碼即可
- Html 核心程式碼 (至於樣式的優化,文檔中有,自行融合唄)
<!-- 中國使用 --> <script type="text/javascript" charset="utf-8" src="//g.alicdn.com/sd/ncpc/nc.js?t=2015052012"></script> <div id="your-dom-id" class="layui-form-item nc-container"></div> <input type="hidden" class="nc_token" name="nc_token" value="X">
- js 核心程式碼:
var nc_appkey = "Your appkey";//寫入自己的 appkey var nc_token = [nc_appkey , (new Date()).getTime(), Math.random()].join(':'); var NC_Opt = { renderTo: "#your-dom-id", appkey: nc_appkey , scene: "nc_login", token: nc_token, customWidth: 300, trans:{"key1":"code0"}, elementID: ["usernameID"], is_Opt: 0, language: "cn", isEnabled: true, timeout: 3000, times:5, callback: function (data) { //window.console && console.log(nc_token); //console.log('sss',data); //TODO 此處 toUrl 即為後台驗證鏈接,根據自己的業務定義即可 var toUrl = "{:url('cms/login/ajaxAfsCheck')}"; $.post( toUrl, data, function (result) { if (result.status == 1) { $(".nc_token").val(nc_token); } else { //失敗 layer.msg(result.message); } }, "JSON"); } }; var nc = new noCaptcha(NC_Opt); nc.upLang('cn', { _startTEXT: "請按住滑塊,拖動到最右邊", _yesTEXT: "驗證通過", _error300: "哎呀,出錯了,點擊<a href="javascript:__nc.reset()">刷新</a>再來一次", _errorNetwork: "網路不給力,請<a href="javascript:__nc.reset()">點擊刷新</a>", });
㈢ 服務端程式碼集成
此時可以根據 【滑動驗證服務端程式碼集成文檔
】,進行整合處理
- 在【
雲盾·人機控制台
】下載對應語言的SDK 以鄙人的ThinkPHP5.1.2框架環境
,服務端 SDK程式碼放置位置參考:
- 應用伺服器 請求處理類的設計: 此驗證方法即為前端js中回調所觸發的請求鏈接地址 注意:
YOUR ACCESS_KEY、YOUR ACCESS_SECRET請替換成您的阿里雲子帳號(RAM用戶)的 accesskey id和secret ; YOUR APP_KEY 寫入自己的 appkey
/** * ajax 測試阿里雲滑動驗證 * @param Request $request * TODO YOUR ACCESS_KEY、YOUR ACCESS_SECRET請替換成您的阿里雲子帳號(RAM用戶)的 accesskey id和secret * YOUR APP_KEY : 寫入自己的 appkey */ public function ajaxAfsCheck(Request $request) { if ($request->isPost()) { $postData = $request->post(); include_once '../extend/aliyun/aliyun-php-sdk-core/Config.php'; $iClientProfile = DefaultProfile::getProfile("cn-hangzhou", "YOUR ACCESS_KEY", "YOUR ACCESS_SECRET"); $client = new DefaultAcsClient($iClientProfile); DefaultProfile::addEndpoint("cn-hangzhou", "cn-hangzhou", "afs", "afs.aliyuncs.com"); $request = new AfsAuthenticateSigRequest(); $ip = get_real_ips(); //自定義的一個獲取IP地址的方法 $request->setSessionId($postData["csessionid"]);// 必填參數,從前端獲取,不可更改,android和ios只傳這個參數即可 $request->setToken($postData['token']);// 必填參數,從前端獲取,不可更改 $request->setSig($postData['sig']);// 必填參數,從前端獲取,不可更改 $request->setScene('nc_login');// 必填參數,從前端獲取,不可更改 $request->setAppKey("YOUR APP_KEY");//必填參數,後端填寫(寫入自己的 appkey) $request->setRemoteIp($ip);//必填參數,後端填寫 $response = $client->getAcsResponse($request);//返回code 100表示驗簽通過,900表示驗簽失敗 $opTag = ($response->Code === 100) ? 1 : 0; $message = ($response->Code === 100)? "驗簽通過":"驗簽失敗"; if ($opTag){ Session::set('NC_TOKEN',$postData['token']); }else{ Session::set('NC_TOKEN','NULL'); } } else { $opTag = 0; $message = "請求不合法"; } return showMsg($opTag, $message,$response); //就是返回 json_encode()處理後的數據 }
㈣ 後期處理以及效果
在前面的操作完成後,按照完整的業務處理邏輯,緊接著就是要處理登錄按鈕的觸發事件了
> 鄙人的操作是: 在登錄按鈕觸發的 ajax 請求驗證中; 判斷當前 Session 中的 "NC_TOKEN " 是否和 前端隱藏域傳來的 "nc_token" 值相等 ; 如果相等,說明已成功滑動驗證通過,繼而判斷帳號和密碼是否能成功登錄; 反之提示刷新再次進行驗證 ...
- 執行效果圖:
附錄:
- 頻繁查看的鏈接:【
雲盾·人機控制台
】 - 一方面覺得寫得太詳細了,有點顯得冗雜了,其實看文檔仔細點也是沒問題的 提示:多留意一下,我在
"㈠ 前期準備"
中提及的資訊,尤為重要!! - 補充,後台獲取IP 地址的函數:
/** * 此方法返回用戶的IP地址,同時如果擁有代理IP,將會以逗號追加在後面 * 如果只取用當前IP,可參考 : * $ips = explode(',', $bargainModel->get_real_ips()); * $ip = $ips[0]; */ function get_real_ips() { global $ip; if (getenv("HTTP_CLIENT_IP")) { $ip = getenv("HTTP_CLIENT_IP"); } else if (getenv("HTTP_X_FORWARDED_FOR")) { $ip = getenv("HTTP_X_FORWARDED_FOR"); } else if (getenv("REMOTE_ADDR")) { $ip = getenv("REMOTE_ADDR"); } else { $ip = "NULL"; } return $ip; }