DIY CAPTCHA開発

今日、スパムボットなどの紳士のおかげで、生成された画像から文字を入力せずにネットワーク上で何かを行うことはほとんど不可能です-CAPTCHA (以降-captcha) 。 実際、これにより、人間の介入なしでスクリプトの実行が防止されます。このトピックでは、PHPツールを使用してそのようなキャプチャを作成する方法を説明し、キャプチャイメージを開発するときに役立つ別のhabrayuzerから非常に有用なトピックに言及します。



私はすぐに、このトピックは初心者の開発者だけに興味があるかもしれないと警告します。実際、私は自分で自転車を発明しています。



基本的なルール



キャプチャを開発するときは、いくつかの基本的なルールに従う必要があります。



1.人のために作成されたCaptcha

すぐに読めるようにすべきですが、認識抵抗を犠牲にする必要はありません。 このルールに準拠していないキャプチャの非常に明確な例は、右側の画像です。



2.キャプチャジェネレーターは、使用する文字を明確に制限する必要があります。

良い例は、トピックの冒頭の画像です。 もちろん、reCAPTCHAは素晴らしい発明ですが、charmapで見つけるのが難しいキャラクターを紹介することもあります。 ちなみに、キリル文字を使用したキャプチャについては、ジェネレータで文字「」を使用しないでください。 個人的には、システムで何らかのアクションを実行している〜(チルダ/)を持っている多くの人々を知っています。



3. Captchaは認識に抵抗する必要があります

...しかし、読みやすさを犠牲にすることはありません。 一般的に、この項目はすべての開発において最も難しいものです。 妥協点を見つける必要があります-captchaはすぐに人々に読まれ、一般的に(可能な限り)ボットには読まれません。 また、captchaを使用する予定のリソースとその条件の詳細を考慮する必要があります。 たとえば、40歳以上の主婦を読むフォーラムについて話している場合は、高い塔からのキャプチャの強さに唾を吐くことができます-それは誰にも休まないでしょう。 たとえば、イメージボードについて話している場合、captcha a la vyrviglazが必要です。



設計



適度に攻撃的で、適度に賢く、一般に適度なユーザーがいる真空の球形フォーラムは、私たちがキャプチャする理論的なオブジェクトとして機能します。 このようなキャプチャの開発では、パスタファリストのhabrayuzerからの非常に有用なトピックが役立ちます。 すなわち、私は彼が取ったキャプチャのリストされた欠点と利点に注意を払います。



したがって、使用できるものを順番にリストします。



1.画像には少なくともいくつかの色を使用する必要があります。 常に望ましい









上の画像は、実際の動作の例です。 実際、背景とテキストが非常に対照的であるため、これは非常に信頼できるオプションではありません。 後で花を扱います。



2.ノイズがなければなりません









共通の真実。 ほぼすべてのキャプチャで、ノイズを見つけることができます。ノイズは、テキストを横切る多くの線で表現され、長さや角度が異なります。



3.文字は互いに短い距離にある必要があります









ここでの主なことは無理をしないことです。 文字が過度に収束すると、人間の可読性が大幅に低下します。 上記の例では、文字がくっついていることに気付くことができます。これにより、画像を分割するときにボットに障害が発生します。



4.文字サイズは異なる必要があります









このトリックを適用する場合、ボットが定数マトリックスを使用してキャプチャをセグメント化することができないという事実で障害物が実際に表現されることを覚えておく必要があります。 したがって、文字のサイズを変更する場合は、各文字のサイズがランダムで動的であることを確認してください。



5.嫌なフォント









非常に便利な方法。 セリフ、斜体、様式化は、ボットの優れた落とし穴です。 また、線の形のノイズと組み合わせて、細いフォントは非常によく見えます。 キャプチャ生成の最初のルールを無視する場合、たとえば、各文字に独自のフォントなど、多くのフォントを一度に使用できます。



6.ランダムな角度のシンボル











ボットから身を守る非常に効果的な方法。 繰り返しますが、セグメンテーションはそれほど複雑ではありませんが、複雑になります。 小さい角度範囲を選択することをお勧めします。そうしないと、読みやすさが大きく低下します(文字が互いに向かって流れます)。



7.動的歪み











人類はそれ以上悪いものを発明していません。 キャプチャの歪みは、多くの場合、人間の可読性を大幅に低下させます。 もちろん、これはボットに対して非常に効果的ですが、人々に対しても効果的です。 主なことは無理をしないことです;歪みは取るに足らないものでなければなりません。



それで、私たちは何をしますか:

-ノイズを含むコントラスト背景

-テキストの行、テキストの行

-ランダムな位置のテキスト

-文字数は4から7までランダムです

-各キャラクターのサイズはランダムです

-テキストの色は毎回ランダムになります

-シンボルはわずかに触れます

-各キャラクターはランダムな小さな角度になります



開発



目標を決定します。

-ノイズ生成

-テキスト生成

-キャプチャを更新する機能を備えたフォーム

-入力データプロセッサ

記事を書いたとき、この場合の歪みは絶対に不適切であることに気付きました。 まだそれらを必要とする人のために-トピックの最後に、歪みの作成に関するレッスンへのリンクがあります。



フォームを書く


<form action="go.php" method="post" enctype="multipart/form-data"> <!--        go.php  POST --> <img src='captcha.php' id='capcha-image'> <!--   --> <a href="javascript:void(0);" onclick="document.getElementById('capcha-image').src='captcha.php?rid=' + Math.random();"> </a> <!--    .   captcha.php  . --> <span> :</span> <input type="text" name="code"> <input type="submit" name="go" value=""> <!--   - go.php --> </form>
      
      





ここではすべてが明確になっていますが、念のため、いくつかの行についてコメントしました。 ところで、入力フィールドでmaxlenghtパラメーターを設定しなかったことに注意してください。 ほとんどの場合、開発者はこのパラメーターを設定して、キャプチャのサイズを示します。 第一に、これはボットにとって非常に良いヒントであり、第二に、キャラクターの数は動的です。 これで、作成したインターフェイス、生成スクリプトの作成を開始します



キャプチャコードジェネレーター(random.php)の作成


 <?php //    function generate_code() { $chars = 'abdefhknrstyz23456789'; //  ,   .    . $length = rand(4, 7); //   ,    -  4  7 $numChars = strlen($chars); // ,      $str = ''; for ($i = 0; $i < $length; $i++) { $str .= substr($chars, rand(1, $numChars) - 1, 1); } //   // ,    $array_mix = preg_split('//', $str, -1, PREG_SPLIT_NO_EMPTY); srand ((float)microtime()*1000000); shuffle ($array_mix); //    return implode("", $array_mix); } ?>
      
      





すべてはあなたの想像力によってのみ制限されます。 どういうわけか私は別の方法を見ました-現在の分、時間、月が選択され、それがすべて乗算され、10個のランダムな文字がこれから選択され、MD5ハッシュが2回抽出され、6個のランダムな文字が抽出され、その後すべてが混同されました。 ところで、私が選択したシンボルに注意してください-私はi、l、1と0、o、cなどを除外しました、それらは互いにあまりにも似ているという事実のために、状況によってはユーザーがミスをするかもしれません。 ジェネレーターrandom.phpを呼び出しました(後で他のスクリプトで要求されます)。



画像ジェネレーターの作成(captcha.php)


 <?php //   img_dir,          ( )  define ( 'DOCUMENT_ROOT', dirname ( __FILE__ ) ); define("img_dir", DOCUMENT_ROOT."/captcha/img/"); //    ,        $HTTP_SERVER_VARS.   ,      . // define("img_dir", "/captcha/img/"); //    include("random.php"); $captcha = generate_code(); //   (  -      go.php) // session_start(); // $_SESSION['captcha']=$captcha; // session_destroy(); //     .    120 . $cookie = md5($captcha); $cookietime = time()+120; //      setcookie("captcha", $cookie, $cookietime); //     function img_code($code) // $code -   ,       { //   Header' header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Last-Modified: " . gmdate("D, d MYH:i:s", 10000) . " GMT"); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", false); header("Pragma: no-cache"); header("Content-Type:image/png"); //  .  ,      (    ).   ,  3  7. $linenum = rand(3, 7); //    .         /img.   - 15070.      $img_arr = array( "1.png" ); //   .    ,     $font_arr = array(); $font_arr[0]["fname"] = "DroidSans.ttf"; //  .   Droid Sans,  ,    . $font_arr[0]["size"] = rand(20, 30); //   pt //  ""      $n = rand(0,sizeof($font_arr)-1); $img_fn = $img_arr[rand(0, sizeof($img_arr)-1)]; $im = imagecreatefrompng (img_dir . $img_fn); //     for ($i=0; $i<$linenum; $i++) { $color = imagecolorallocate($im, rand(0, 150), rand(0, 100), rand(0, 150)); //   c  imageline($im, rand(0, 20), rand(1, 50), rand(150, 180), rand(1, 50), $color); } $color = imagecolorallocate($im, rand(0, 200), 0, rand(0, 200)); //   .   . //    $x = rand(0, 35); for($i = 0; $i < strlen($code); $i++) { $x+=15; $letter=substr($code, $i, 1); imagettftext ($im, $font_arr[$n]["size"], rand(2, 4), $x, rand(50, 55), $color, img_dir.$font_arr[$n]["fname"], $letter); } //  ,    for ($i=0; $i<$linenum; $i++) { $color = imagecolorallocate($im, rand(0, 255), rand(0, 200), rand(0, 255)); imageline($im, rand(0, 20), rand(1, 50), rand(150, 180), rand(1, 50), $color); } //    ImagePNG ($im); ImageDestroy ($im); } img_code($captcha) //   ?>
      
      





すべてのコードは可能な限りコメントアウトされています。 入力されたキャプチャハンドラを確認するには、そのハッシュをCookieに追加します。 フォントと背景を選択するために、配列を作成して、そこに数十個のフォントと数十個の背景を配置できるようにしました。毎回ランダムなものが選択されます。 フォントはDroid Sansを選択しました。それは薄く、ノイズの中でも目立ちません。 ちなみに、この場合、ひどい、嫌な、対照的な背景を選んだので、デモはトピックの最後になります。 驚いたことに、これは人間の可読性には影響しませんでした。フォントの色は背景のランダムなピクセルから選択されているにもかかわらず、フォントは非常に際立っています。



ハンドラーの作成(go.php)


 <META http-equiv=content-type content="text/html; charset=UTF-8"> <?php include("random.php"); $cap = $_COOKIE["captcha"]; //     MD5 ,    captcha.php //      function check_code($code, $cookie) { //   $code = trim($code); //      $code = md5($code); //    ! //   ,   -     captcha.php,  ,    //session_start(); //$cap = $_SESSION['captcha']; //$cap = md5($cap); //session_destroy(); if ($code == $cap){return TRUE;}else{return FALSE;} //    -  TRUE (  - false) } //    if (isset($_POST['go'])) //  ,    : ,    . { //     ( POST-  'code' )... if ($_POST['code'] == '') { exit(":  !"); //...   } //     (  TRUE), ... if (check_code($_POST['code'], $cookie)) { echo "   .    ,  ."; //     } //    ... else { exit(":   !"); //...   } } //     ,   ... else { exit("Access denied"); //...,   } ?>
      
      





ここではすべてが非常に明確です。 以前にcaptcha.phpに記録されたCookieを取得し、入力されたコード、より正確にはそのハッシュを取得して比較します。 注意! このコードを使用する予定がある場合は、検証アルゴリズムを変更することを忘れないでください。



結果





結果は非常に良好で、私の期待を完全に満たしました(不可解なキャプチャを作成するという目標を自分で設定しなかったことに注意してください)。 ここで耐久性をテストできます (私のサーバーがhabraeffectに該当しないことを願っています)。

実際、私のコードは単なるテンプレートであり、好きなようにモックできます。 そして実際、これは必要ありません-reCaptchaがありますが、ドキュメントの山を読んでいる間、私は個人的にこのスクリプトを行うことを喜んでいます。誰かが私のトピックから知識を引き出すことを望みます:)



フッター



約束されたように、誰かが便利な場合に、テキストを歪めるための非常に便利なコードを次に示します。



トマトを投げないでください:)これはHabrに関する私の最初の技術トピックです。

そして、はい、現代のキャプチャがどのように機能するのかわかりません。このトピックに関する情報を探していませんでした。 私の方法がインド人に思える場合は、PM /コメントですぐにそれを書くようお願いします。私の方法の短所のうち、ブラウザでCookieが有効になっていない場合のみ、このキャプチャを通過できません。



All Articles