آیا واقعا نیاز به کپچا دارید؟

کپچا حصاری است برای محافظت از سیستم شما، که از آن سوء استفاده نشود. ممکن است از آن برای محافظت از دیدگاه‌ها در برابر اسپم و یا در فرم ثبت‌نام استفاده شود. اما این حصار برای کاربران شما نیز مشکل ایجاد خواهد کرد و آن‌ها را اجبار به انجام یک کار اضافی می‌کند. گاهی اوقات می‌توان از آن استفاده نکرد. قبل از آن‌که از کپچا استفاده کنید به مثال‌های زیر که با پی‌اچ‌پی نوشته شده‌است توجه کنید، شاید نیازی به استفاده کپچا نداشته باشید.

۱. استفاده از Timeout/Session Token در فرم

شما می‌توانید از کاری که برای جلوگیری از حملات CSRF انجام می‌دهید، استفاده کنید. ایده این است که قبل از این‌که فرم شما توسط POST فرستاده شود، مطمئن شوید آن توسط GET گرفته شده‌است. ربات‌های خودکار معمولا از مرحلهٔ گرفتن فرم با استفاده از GET صرفنظر و مستقیم آن را POST می‌کنند.

اگر شما از session store برای نگهداری وضعیت استفاده می‌کنید، می‌توان از session salt که به صورت تصادفی تولید شده‌است، استفاده کنید:

  <?php
  session_start();
  if (!isset($_SESSION['salt'])
    $_SESSION['salt'] = sha1(uniqid());

  // ... [snip] ...

  // check salt on submission
  if (count($_POST) && !$_POST['salt']===$_SESSION['salt']) {
    // error condition, redisplay form
  }

  // ... [snip] ...

  // include salt in requested form
  echo "<input type=hidden name=salt value=$salt>";

اگر شما از session state استفاده نمی‌کنید، این کار را می‌توان با استفاده از timeouts در فرم که امضا (signed) شده‌است، پیاده کرد.

    <?php
    define('SALT','My^%*&SecretSalt');

    // ... [snip] ...

    // include signed request time in form
    $now = time(); $signed = $now.'#'.sha1(SALT.$now.SALT);
    echo "<input type=hidden name=requested value=$signed>";

    // ... [snip] ...

    // check timeout on submission
    if (count($_POST)) {
      list($when,$hash) = explode('#',$_POST['requested'],2);
      if ($hash!==sha1(SALT.$when.SALT) || $when<(time()-30*60)) {
        // error condition, redisplay form; either
        // corrupted or the form was served > 30 minutes
        // ago
      }
    }

۲. ظرف عسل یا کپچای برعکس

با استفاده از ظرف عسل یا کپچای برعکس می‌توان تعداد ربات‌هایی در وب‌گاه شما وارد می‌شوند را شمرد. معمولا ربات‌ها تمام فیلدها را پر می‌کنند و تمام checkboxها را تیک می‌زنند. شما می‌توانید یک checkbox تعریف کنید و با کمک CSS آن را مخفی کنید که کاربر معمولی نتواند آن را ببیند. کسانی که آن checkbox را تیک می‌زنند یقینا ربات هستند.

    <?php
    if (isset($_POST['honeypot'])) {
      // error condition, redisplay form
    }
    ?>

    ...
    <label style="display:block;position:absolute;left:-9999px">
      Please leave this checkbox blank
      <input type=checkbox name=honeypot value=1>
    </label>
    ...

۳. فیلدهایی با نام پویا

سوء استفاده از یک فرم که نام فیلدهای آن در بین درخواست‌ها ثابت باشد، خیلی ساده است. اگر شما از session/timeout token برای محافظت فرم خود استفاده می‌کنید، می‌توانید نام فیلدها را براساس آن token تغییر دهید. تنها مشکلی که این روش دارد این است که موتور autocomplete مرورگرها نمی‌توانند نام فیلدها را به دلیل پویا بودن تشخیص دهند.

    <?php
    define('SALT','My^%*&SecretSalt');
    function fieldname($name,$salt) {
      return sha1($name.$salt.SALT);
    }

    // submitted
    if (count($_POST)) {
      $token = $_POST['token'];
      list($when,$hash) = explode('#',$token,2);
      if ($hash!==sha1(SALT.$when.SALT) || $when<(time()-30*60)) {
        // error (over 30min timeout)
      }
      $fn = fieldname('comment',$token);
      $comment = isset($_POST[$fn]) ? $_POST[$fn] : null;
      if (!$comment) {
        // error (no comment submitted)
      }
      // etc
    }

    // ... [snip] ...

    // create token
    $now = time(); $token = $now.'#'.sha1(SALT.$now.SALT);
    ?>

    ...
    <label>Comment
      <textarea name="<?php echo fieldname('comment',$token); ?>"></textarea>
    </label>
    <input type=hidden name=token
        value="<?php echo $token; ?>">
    ...

۴. فیلترهای «فازی»

فیلترهای فازی می‌تواند برای برنامه یا وب‌گاه شما مناسب و کارا باشد. برای مثال دیدگاه‌های یک وبلاگ می‌تواند فورا منتشر شود و یا این‌که آن دیدگاه به صف مدیریت فرستاده شود که آن صف مدیریت می‌تواند تشخیص دهد که می‌تواند آن منتشر شود یا خیر. آن صف مدیریت می‌تواند براساس فاکتورهای از پیش تعریف شده احتمال اسپم بودن و یا نبودن را محاسبه کند و اگر احتمال اسپم بودن بالا بود آن را در دستهٔ فرستاده‌شده‌ها توسط ربات دسته‌بندی کند.
این فاکتورها برای شما ممکن است متفاوت باشد، اما می‌توان فاکتورهای زیر را برای دیدگاه‌های یک وبلاگ تعریف کرد:

  • آیا دیدگاه فرستاده شده دارای referrer معتبر است؟ فرم دیدگاه شما از کجا فرستاده شده‌است؟
  • اگر فرم شما دارای زمان باشد (همانطور که گفته شد) چه مقدار زمان برای پر کردن آن وقت صرف شده‌است؟ آیا کمتر از ۲ ثانیه است؟ اگر این‌طور باشد به احتمال بالایی دیدگاه از سوی یک ربات فرستاده شده‌است.
  • آیا دیدگاه دارای یک URL است؟ معمولا این هدف یک اسپم است.
  • آیا User-Agent مربوط به یک مرورگر عادی است؟
  • آیا این دیدگاه از سوی کاربری فرستاده شده‌است که هویتش مشخص شده‌است؟ آیا قبلا نیز دیدگاهی ارسال کرده‌است؟
هیچ‌کدام از فاکتورهای بالا به تنهایی نمی‌توانند مشخص کنند که دیدگاه توسط یک ربات فرستاده شده‌است، اما احتمال فرستاده شدن توسط ربات را بالا می‌برد. اگر احتمال اسپم بودن یک دیدگاه بالا بود می‌توانید آن را به صف مدیریت بفرستید و اگر احتمال اسپم بودن پایین بود، آن‌را منتشر کنید.

۵. مراحل پیش‌نمایش/تایید

شرایطی که گفته شد می‌تواند یک فرم یک مرحله‌ای را محافظت کند. فرم‌های چندمرحله‌ای بسیار کار را برای ربات‌های خودکار سخت می‌کند. اگر فرم شما ساده است، می‌توانید یک مرحله تایید هم به فرم اضافه کنید.

بعدی؟

اگر با در نظر گرفتن مراحل بالا هنوز ربات‌ها مزاحم شما می‌شوند، وقت پیاده‌سازی یک کپچا فرا رسیده‌است. روش‌های بالا باعث کاهش حملات می‌شود اما حملات را کاملا از بین نمی‌برد. اضافه کردن کپچا هم کار را برای ربات‌ها سخت‌تر می‌کند، اما غیرممکن نمی‌کند و برنامه یا وب‌گاه شما کامل امن نمی‌شود.
نظر موافقان و مخالفان کپچای متنی را بخوانید