本教程主要針對為laravel 6 配置reCAPTCHA v2.0 checkbox的情況
第一部分: 什麼是reCAPTCHA?為何要配置它?如何選擇適合自己網站的身份驗證方式?
1.1 reCAPTCHA是什麼?
1.2 reCAPTCHA的優缺點
1.3 laravel驗證碼平行比較:mews/captcha?為何選擇reCAPTCHA?
1.4 reCAPTCHA的各個版本介紹,及如何選擇自己適用的reCAPTCHA:
1.5 為何選擇自行配置reCAPTCHA,而不是使用目前已有的、已經整合在laravel系統的包?
第二部分:為laravel6配置reCAPTCHA v2.0 checkbox 的手把手教程
2.1 安裝含有auth的全新laravel 6程式
2.2 配置reCAPTCHA
2.3 bonus:如何相容中文
之前緊急為站點配置了google reCAPTCHA驗證系統,避免盜號攻擊。將經驗總結寫作下列教程,回饋社群。
為了方便講解,本教程在空白laravel 6基礎上編寫,具有詳細的逐步過程。雖然我們的實際生產環節只在5.7框架版本使用,我們相信這個教程中提到的方法在5.7之後版本的laravel專案裡也會保持穩定。
1.1 reCAPTCHA是什麼?
reCAPTCHA 是 CAPTCHA 的衍生詞。CAPTCHA是 Completely Automated Public Turing test to tell Computers and Humans Apart 的縮寫,意為“全自動區分計算機和人類的圖靈測試”。reCAPTCHA是谷歌基於這個思路開發的一套具體的驗證規則。目前,它具有多個版本。
1.2 reCAPTCHA的優缺點
優點:
- 獨立的軟體包,安裝和“拆卸”都便利
- 聯網谷歌,根據往期記錄決定使用者的“真實性”,相對難以破解,更安全。
- 免費
缺點:
- 聯網谷歌,你懂的,有那麼一點點……聯網問題。
- 語言需要額外配置。
- 其中一部分驗證的思維方式,可能不太符合中文語境的生活經驗與使用習慣。
1.3 laravel驗證碼平行比較:reCAPTCHA VS mews/captcha
提到reCAPTCHA
,不得不先介紹laravel的另一個常用的驗證碼系統 mews/captcha
。
mews/captcha
是集合在laravel系統上的一個方便好用美觀的圖片驗證碼系統。它隨機生成一個含有邀請碼字元的圖片,要求使用者進行識別,輸入圖上的字元,完成驗證。官方程式碼地址:https://github.com/mewebstudio/captcha
這個系統文件完備,非常方便配置,而且對於流量不高的普通個人工程來說,具有不錯的防護效果。mews/captcha
本身的安裝文件就很完整,可以直接照著安裝。如果你想要中文的安裝介紹,可以參考這個網址:分享:【擴充套件推薦】mews/captcha 圖片驗證碼解決方案
之前研究過很多目前已有的、免費可用的、相容laravel的驗證碼系統。坦誠地說,如果你是剛開始進行建站的開發者,使用laravel,又需要配置驗證碼,mews/captcha
是你的首選。儘量主要精力花在你的核心服務邏輯上。
但是……我們實際使用 mews/captcha
的悲慘結果是,它比較容易被破解。基於本站實際體驗,後臺資料跟蹤發現,在使用它的第一個月,預設版式的驗證碼被破解。更換到inverse圖片之後的大概第二個月,“inverse”版式也被破解了。
因此,緊急更換並配置reCAPTCHA,成了我們被迫的、無奈的結果。
1.4 reCAPTCHA的各個版本介紹,及如何選擇自己適用的reCAPTCHA:
reCAPTCHA v1.0:已廢棄
reCAPTCHA v2.0: 目前主流使用的reCAPTCHA系統,具有下面幾個“變種”:
- “im not a bot checkbox” 通過點選方框,決定使用者是否真人。如果使用者的“可疑性”比較高,進一步要求使用者做圖片識別(比如找公交車、找人行橫道……)直到使用者作出正確的判斷再放行。
- “invisible”recaptcha 隱藏在幕後,直接通過使用者的行為判斷是否真人的recaptcha,是reCAPTCHA 3.0 的前置產品。個人理解,目前的v3.0基本完全覆蓋了這部分的功能,因此沒有采用的必要。
- 專門適用android的recaptcha
reCAPTCHA v3.0:最新推出的reCAPTCHA
只對網站提供使用者的安全分值(0-1,1代表真人,0代表bot),由網站自行判斷下一步要做什麼。
結論1: 對於個人非安卓的開發者,只需要從reCAPTCHA v2.0 checkbox和reCAPTCHA v3.0中挑一個就可以了。
以下繼續分點闡述這兩個版本recaptcha的好壞比較,方便使用者選擇最適合自己的驗證方式:
reCAPTCHA v2.0 checkbox
主要好處:
- 有預置的fallback。如果使用者的分數較為可疑,並不會拒絕使用者,而是要求使用者用進一步的圖片識別繼續驗證自己身份,驗證之後就允許訪問。
主要壞處:
- 圖片識別過程非常繁瑣,可能會有較多的使用者抱怨(類似:“為什麼我每次登陸都要點六十次立交橋”。當然後來我們發現這跟使用者的瀏覽器用了什麼也有關係)
reCAPTCHA v3.0
主要好處:
- 可以用在你網站的所有頁面(無論是否含有表單),並根據不同的頁面配置不同的處理決定
- 可以根據實際情況,自定義對分數的後續處理(比如說,在某些網站,0.5是可疑使用者不能允許訪問,而在另一些網站,沒必要阻止0.5的使用者訪問)
主要壞處:
- 如果你因為分數很低直接拒絕了某些使用者,你可能會永久地失去他們。因此,recaptcha3.0需要自行配置合理的fallback辦法,這對個人開發者來講是一個比較大的業務負擔。
結論2: 目前reCAPTCHA 3.0並不能直接取代reCAPTCHA 2.0 checkbox(這可能也是為什麼谷歌並沒有停止2.0業務的原因)。開發者應根據自己的情況自主選擇,而不是片面升級到最新版本的reCAPTCHA。
結合專案當前的主要需求:在註冊、登陸等重要頁面進行身份驗證,避免bot攻擊,但也不要把真人踢走的需求,我們選擇reCAPTCHA v2.0 checkbox作為新的驗證手段。
主要是因為,大部分laravel和reCAPTCHA系統的整合包,並不支援reCAPTCHA的global配置(也就是說會被牆),需要自己進行微小的調整。其次,因為命名的問題,他人的reCAPTCHA整合包,可能會和其他的驗證碼方式衝突,如果開發者打算在系統里加入多個驗證方式,需要特別注意這一點。
實際上,個人自行配置reCAPTCHA非常簡單,也很靈活,命名衝突也非常好解決。
接下來的教程裡,將新建一個全新空白laravel工程,併為它配置reCAPTCHA v2.0 checkbox系統
全部程式碼見:https://github.com/lyn510/reCAPTCHA
我們這就開始吧!
2.1 安裝含有auth的全新laravel6程式
首先安裝一個版本為 laravel 6 的全新程式。 這和laravel5的配置過程會略有不同。
$ composer create-project laravel/laravel reCAPTCHA
接下來安裝預設的auth身份驗證方式(就是基礎的登陸註冊系統)
$ composer require laravel/ui --dev
上面的指令安裝了預設ui
$ php artisan ui vue --auth
上面的指令安裝了登陸介面
$ npm install && npm run dev
上面指令會compile對應的css檔案,讓ui介面的內容得以被呈現出來。它會需要比較長的時間來執行,視網路環境而定,請耐心等待。
接下來,為了正常使用登陸系統,需要建立對應的資料庫。本教程裡使用的是mysql。
建立一個mysql資料庫,資料庫的名字叫reCAPTCHA-auth
, 使用者名稱root
, 密碼留空。
配置.env
檔案,使程式能連線到資料庫:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=reCAPTCHA-auth
DB_USERNAME=root
DB_PASSWORD=
之後,回到terminal,執行migrate命令
$ php artisan migrate
接著檢視一下目前的情況
$ php artisan serve
從瀏覽器開啟對應的連結http://127.0.0.1:8000
,就可以正常的登陸系統。(在terminal中,執行 control+C,就可以退出)。
2.2 配置reCAPTCHA
下面,我們將reCAPTCHA安排進來。
2.2.1 首先使用composer,安裝官方包:
$ composer require google/recaptcha
接著一步步完成後端的配置。
2.2.2 建立一個extended validator來進行對應的測試。
新建檔案:app\Validators\reCaptchaCheckbox.php
<?php
namespace App\Validators;
use ReCaptcha\ReCaptcha;
class reCaptchaCheckbox{
public function validate($attribute, $value){
$captcha = new ReCaptcha(env('RECAPTCHA_CHECKBOX_SECRET'));
$response = $captcha->verify($value, $_SERVER['REMOTE_ADDR']);
return $response->isSuccess();
}
public function message($message, $attribute, $rule, $parameters){
return ;
}
}
下面將validator註冊進入預設的validation系統
修改app\Providers\AppServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
// 增加這行程式碼,擴充套件預設 Validator
Validator::extend('recaptcha', 'App\Validators\reCaptchaCheckbox@validate');
}
}
上面這裡要增加兩行程式碼,一行排程validator,另一行擴充套件validator的boot方式。
2.2.3 接著我們要求,在使用者登入(login)的時候,需要首先進行人機驗證。
修改檔案app\Http\Controllers\Auth\LoginController.php
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* @var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
// 這裡,重寫login方式,使得recaptcha的驗證成為這部分必須的驗證環節
public function login(Request $request)
{
$request->validate([
'g-recaptcha-response' => 'required|recaptcha'
]);
$this->validateLogin($request);
if ($this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
if ($this->attemptLogin($request)) {
return $this->sendLoginResponse($request);
}
$this->incrementLoginAttempts($request);
return $this->sendFailedLoginResponse($request);
}
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest')->except('logout');
}
}
2.2.4 再下面,我們要求前端展示這個人機驗證的檢視
修改檔案resources\views\auth\login.blade.php
...
<div class="g-recaptcha" data-sitekey="{{ env('RECAPTCHA_CHECKBOX_SITEKEY') }}"></div>
<button type="submit" class="btn btn-primary">
{{ __('Login') }}
</button>
修改檔案resources\views\layouts.app.blade.php
...
<!-- Scripts -->
<script src="{{ asset('js/app.js') }}" defer></script>
<script src="https://www.recaptcha.net/recaptcha/api.js"></script>
...
注意上面這裡,使用www.recaptcha.net
,而非www.google.com
,來避免在大陸的訪問被牆。
2.2.5 最後別忘了配置開發者專用的key
首先登陸Recaptcha註冊官網:https://www.google.com/recaptcha/admin#lis...
選擇v2 checkbox,輸入對自己網站的配置即可
此處domain選填了127.0.0.1,因為有本地測試情況。使用valet的朋友,在這裡新增valet的域名縮寫(比如xxxxxx.test
),親測也是可以有效完成本地測試的。
確認後,就會獲得相關key
配置到.env
裡:
RECAPTCHA_CHECKBOX_SECRET=6Lc6u8oUAAAAAPI4a0lYImLIWyR50xxxxxxxx
RECAPTCHA_CHECKBOX_SITEKEY=6Lc6u8oUAAAAALvO2Tfjh5zRheJGuyxxxxxxx
所有程式端的配置就完成了
別忘了重新配置目錄
$ composer dump-autoload
重新開啟頁面
$ php artisan serve
此時,只要通過人機測試,就可以正確登陸。
2.3 bonus:如何相容中文
2.3.1 如何配置中文reCAPTCHA介面?
2.3.1.1 方法1: 可以直接要求js配置為中文
修改檔案resources\views\layouts.app.blade.php
...
<!-- Scripts -->
<script src="{{ asset('js/app.js') }}" defer></script>
<script src="https://www.recaptcha.net/recaptcha/api.js?hl=zh-CN"></script>
...
2.3.1.2 方法2: 也可以設定要求js響應系統環境語言。
修改檔案:resources\views\layouts.app.blade.php
...
<!-- Scripts -->
<script src="{{ asset('js/app.js') }}" defer></script>
<script src="https://www.recaptcha.net/recaptcha/api.js?hl={{ app()->getLocale() }}"></script>
...
注意這裡app()->getLocale()需要自己按照官方doc繼續配置多語言,就不再詳細寫了。
2.3.2 如何配置中文reCAPTCHA介面的錯誤反饋?
很簡單,修改檔案resources/lang/zh-CN/validation.php
...
'custom' => [
'g-recaptcha-response' => [
'required' => '請先通過人機身份驗證,再提交資訊。如果相關測試不能正確顯示,請檢查瀏覽器設定。',
]
],
...
之前有一些排版的問題,重新編輯了頁面
本作品採用《CC 協議》,轉載必須註明作者和本文連結