Laravel使用者登入時,使用Google reCAPTCHA V3驗證

在Laravel,加入Google reCAPTCHA來過濾機器人

以下假設都以取得Google reCAPTCHA V3的使用金鑰,若未取得請到Google reCAPTCHA申請

.env

首先,先在.env中設定加入api位置和金鑰

..............
RECAPTCHA_ENABLE=true
RECAPTCHA_URL=https://www.google.com/recaptcha/api/siteverify
RECAPTCHA_SITE_KEY=your-site-key
RECAPTCHA_SECRET_KEY=your-secret-key

如果伺服器在長城後面的話,可以嘗試使用https://www.recaptcha.net/recaptcha/api/siteverify替換RECAPTCHA_URL

Blade

在需要驗證的blade中加入以下內容

<form action="/auth/user/login" method="POST">
    @csrf
    <input type="hidden" name="google_recaptcha_token" id="ctl-recaptcha-token">
    ......
    ......
</form>

......
......


<script src="https://www.google.com/recaptcha/api.js?render={{env('RECAPTCHA_SITE_KEY')}}"></script>
<script>
    grecaptcha.ready(function() {
    grecaptcha.execute('{{env('RECAPTCHA_SITE_KEY')}}').then(function(token) {
       document.getElementById('ctl-recaptcha-token').value = token;
    });
});
</script>

如果客戶在長城後面的話,可以嘗試使用https://www.recaptcha.net/recaptcha/api.js

Rules

先使用artisan建立Rule Case或在app/Rules下新增

$ php artisan make:rule GoogleRecapchaV3Case
Rule created successfully.

如下,串連Google reCAPTCHA api

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;
use GuzzleHttp\Client;

class GoogleRecapchaV3Case implements Rule
{
    /**
     * Determine if the validation rule passes.
     *
     * @param string $attribute
     * @param mixed  $value
     *
     * @return bool
     */
    public function passes($attribute, $value): bool
    {
        if (env('RECAPTCHA_ENABLE') == true) {
            return $this->verify($value);
        }

        return true;
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message(): string
    {
        return ':attribute.failed';
    }

    /**
     * Verify token.
     */
    private function verify(string $token = null): bool
    {
        $url = env('RECAPTCHA_URL', 'https://www.google.com/recaptcha/api/siteverify');

        $response = (new Client())->request('POST', $url, [
            'form_params' => [
                'secret' => env('RECAPTCHA_SECRET_KEY'),
                'response' => $token,
            ],
        ]);

        $code = $response->getStatusCode();
        $content = json_decode($response->getBody()->getContents());

        return $code == 200 && $content->success == true;
    }
}

Controller

app/Rules/GoogleRecapchaV3Case加入需要驗證的Controller,並使用$request->validate(['google_recaptcha_token' => new GoogleRecapchaV3Case()])來進行驗證。

以使用者登入為例:


namespace App\Http\Controllers\Auth\Users;

use Illuminate\Http\Request;
............

// Validate Rule
use App\Rules\GoogleRecapchaV3Case;

class LoginController extends Controller
{

    ...................

    protected function validateLogin(Request $request)
    {
        $request->validate([
            $this->username() => 'required|string',
            'password' => 'required|string',
            'google_recaptcha_token' => ['required', 'string', new GoogleRecapchaV3Case()],
        ]);
    }

    ................
}

參考資料

勘誤

  • env未加入RECAPTCHA_ENABLE設定值

其他相關