reCAPTCHA + Laravel + Vue

프런트엔드에 reCAPTCHA Vue 패키지를 구현하고 백엔드에 PHP 패키지를 구현할 것입니다. 그 과정에서 각 단계가 예상대로 작동하는지 확인합니다.

목차


  • Prerequisites
  • 1. Provide reCAPTCHA keys
  • 2. Prepare the front-end
  • 3. Error Handling

  • 전제 조건

    Assumes you have a working Laravel 8 and Vue 2.0 project, Composer and NPM, and a Vue form to which you want to add reCAPTCHA.

    This was built onto a project that uses InertiaJS. However, I believe this should work on a separated front-end and back-end. As such, each sub-section is prefixed with either (Laravel) or (Vue) to indicate to which side the changes belong.

    1. reCAPTCHA 키 제공

    We'll need a valid SITEKEY and SECRET from Google.

    (Laravel) 환경 변수 저장


    .env 파일에 키를 추가합니다.

    NOTE: Do not commit your .env file. You should commit a .env.example with secure values redacted.



    RECAPTCHAV2_SITEKEY=<yoursitekeyhere>
    RECAPTCHAV2_SECRET=<yoursecrethere>
    


    WARNING: Do not expose RECAPTCHAV2_SECRET to the front-end.

    If using VueCLI, environment variables are embedded into the build, meaning anyone can view them by inspecting your app's files. If using VueCLI, Do not store this value in any .env file on Production, not even .env.production. They are auto-loaded by VueCLI. It is okay to expose the SITEKEY, but for the SECRET, use some other secure method in Production, such as setting environment variables without this dotenv file.



    Laravel의 구성에서 이러한 환경 변수를 정의하십시오.
    config/recaptchav2.php 파일을 생성합니다.

    <?php
    return [
        'origin' => env('RECAPTCHAV2_ORIGIN', 'https://www.google.com/recaptcha'),
        'sitekey' => env('RECAPTCHAV2_SITEKEY', ''),
        'secret' => env('RECAPTCHAV2_SECRET', '')
    ];
    


    (라라벨) 프론트엔드와 환경변수 공유



    위의 전제 조건에서 언급한 InertiaJS 조각은 다음과 같습니다.

    이 변경 사항의 요점은 RECAPTCHAV2_SITEKEY 환경 변수를 프런트 엔드와 공유하려는 것입니다.

    InertiaJS를 사용하지 않는 경우 다른 방식으로 Vue에 환경 변수를 제공할 수 있어야 합니다(예: VueCLI를 사용하는 경우 위에서 언급함).

    다음은 InertiaJS 방식입니다.
    app/Http/Middleware/HandleInertiaRequests.php 에서 InertiaJS 미들웨어로 이 작업을 수행합니다.

     public function share(Request $request)
     {
         return array_merge(parent::share($request), [
    +        // Provide the reCAPTCHA site key to the front-end.
    +        'recaptchav2_sitekey' => config('recaptchav2.sitekey'),
    +        // DO NOT SHARE RECAPTCHAV2_SECRET.
         ]);
     }
    


    (Vue) 프론트엔드에 대한 성공적인 공유 보장



    Vue 양식 어딘가에서 임시로 다음을 입력하여 백엔드에서 키가 성공적으로 전달되는지 확인합니다.

     <template>
    +  {{ $page.props.recaptchav2_sitekey }}
       ...
     </template>
    


    This may be different depending on the route taken to expose the environment variable. With VueCLI it would be {{ process.env.RECAPTCHAV2_SITEKEY }}.



    페이지를 탐색하면 사이트 키가 표시됩니다.

    2. 프런트 엔드 준비

    We have a securely stored secret key, and can display the site key on the page. Now, let's get a working reCAPTCHA to appear on the page.

    (Vue) reCAPTCHA Vue 추가



    reCAPTCHA Vue 패키지가 필요합니다.

    npm install --save @vue/composition-api vue-recaptcha
    


    구성 요소에 reCAPTCHA를 추가합니다.

     <template>
    -  {{ $page.props.recaptchav2_sitekey }}
       <form>
         ...
    +    <vue-recaptcha 
    +      :sitekey="$page.props.recaptchav2_sitekey" 
    +    />
       </form>
     </template>
    
    +<script>
    +import { VueRecaptcha } from 'vue-recaptcha';
    +
    +export default {
    +  components: {
    +    VueRecaptcha,
    +  },
    


    이 시점에서 페이지에 표시되고 작동하는 reCAPTCHA가 있어야 합니다.

    3. 백엔드 준비



    (라라벨) 미들웨어 추가




    composer require google/recaptcha
    


    reCAPTCHA 미들웨어 클래스를 정의합니다.

    <?php
    /**
     * @file app/Http/Middleware/Recaptcha.php
     */
    
    namespace App\Http\Middleware;
    
    use Closure;
    use ReCaptcha\ReCaptcha as GoogleRecaptcha;
    
    class Recaptcha
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @return mixed
         */
        public function handle($request, Closure $next)
        {
            $response = (new GoogleRecaptcha(config('recaptchav2.secret')))
                ->verify($request->input('g-recaptcha-response'), $request->ip());
    
            if (!$response->isSuccess()) {
                return redirect()->back()->with('status', 'Recaptcha failed. Please try again.');
            }
    
            return $next($request);
        }
    }
    


    이 새 미들웨어를 /app/Http/Kernel.php에 나열합니다.

     'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
    +'recaptcha' => \App\Http\Middleware\Recaptcha::class,
     'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
    


    그런 다음 이 미들웨어를 양식의 제출 경로에 연결하십시오.

     Route::post('/my-form-action', [
         MyFormController::class, 
         'submitForm'
    -]);
    +])
    +    ->middleware('recaptcha');
    


    (Vue) reCAPTCHA 응답 전달



    reCAPTCHA 백엔드는 프런트 엔드에서 토큰 응답을 기대합니다.

    -    <vue-recaptcha 
    -      :sitekey="$page.props.recaptchav2_sitekey" 
    +      @verify="onCaptchaVerify"
    -    />
     ...
     methods: {
    +  onCaptchaVerify(token) {
    +    // Provide the token response to the form object.
    +    this.form['g-recaptcha-response'] = token;
       },
    


    Note: This assumes you are using a form data object.



    이 시점에서 귀하가 인간임을 확인하고 양식을 제출할 수 있습니다. CAPTCHA 상자를 선택하지 않은 경우 양식을 제출하면 Recaptcha failed. Please try again. 상태로 다시 리디렉션됩니다.

    3. 오류 처리

    On submit, if the reCAPTCHA has failed or has not been attempted, we want to indicate that to the visitor.



    다음을 추가합니다.

     <vue-recaptcha
       :sitekey="$page.props.recaptchav2_sitekey"
       @verify="onCaptchaVerify"
     />
    +<span
    +  v-if="recaptcha_error"
    +  class="error-message"
    +>
    +  Please confirm you are not a robot.
    +</span>
     ...
       data() {
         return {
    +      recaptcha_error: false,
           form: {
             ...
           }
         }
       },
       methods: {
         onSubmit() {
    +      if (!this.form['g-recaptcha-response']) {
    +        // Show error after submit.
    +        this.recaptcha_error = true;
    +      } else {
    +        // Proceed with submission.
    +      }
         }
    


    작동하는 reCAPTCHA를 즐기십시오.

    좋은 웹페이지 즐겨찾기