CAPTCHA。 また?

ドブラス、ハブラフチャン。



免責事項



CAPTCHAは、一意または壊れないことを主張しません。 ただし、一部のボットには間違いなく困難が伴います。 保護部品と同様に、グラフィックと見なされます。 CAPTCHAは私のプロジェクトの1つのために特別に作成されましたが、まだリンクを付けることができません。サーバーは戦闘ではなく、habra効果に耐えられません。 しかし、「スタートアップ」セクションでは、時間が来たらそれについて書きます。



だから、興味がある人-habrakatへようこそ。



開始する



まず、キャプチャの目的を決定します。 もちろん、プロジェクトの不利益に作用するあらゆる種類のプログラムから保護するため。 そしてこれを保護するために、単純なプログラムでは対処できないキャプチャが必要です。 この効果を達成する方法は? まず、信頼できる「クライアント/サーバー」部分が必要です。これは、特定の条件下で非常に簡単にクラッキングできるまさにそのレイヤーです。 2-3 キャプチャを受信した後、攻撃者がそのdomain.ru/captcha-get.php?code= 12345を認識した場合 -これがキャプチャです -クラックするものは何もありません。



さらに、キャプチャを要素に単純に分割し、あらゆる種類の類似性対応によってそれらを決定しようとすることも一般的な慣行です(そしてYandexなどのプロジェクトでも機能します)。 したがって、厳密に別個の要素を選択することは不可能です。



グラフィック部



最長。 多くのコードといくつかの写真。



ポイント1。 テキストを生成します。 PHPで5〜6文字を生成する方法は、多くの人が知っていると思います。 私は最も抵抗の少ない道を取りました。

$text = ""; for($i = 0; $i < 5; $i++){ switch(mt_rand(1,3)){ case(1): {$c=chr(rand(ord('a'),ord('z')));break;} case(2): {$c=chr(rand(ord('A'),ord('Z')));break;} case(3): {$c=rand(0,9);break;} } $text.=$c; }
      
      







ポイント2。 テキストは何らかの画像に表示されるはずです。 私は200x60ピクセルの画像サイズを選択しました-それはちょうど私のニーズとポップアップウィンドウに合っています。

 $im = imageCreateTrueColor(200,60);
      
      







ポイント3。 碑文と十分に対照的な背景が必要ですが、同時に単純に除外することはできません。 私はこの段階でこれを気にせず、単に最終結果に何らかのフィルターをかけることにしました。 それまでの間、背景は純粋にランダムな色になります。



 $white = imageColorAllocate($im, mt_rand(170,255),mt_rand(170,255),mt_rand(170,255)); $black = imageColorAllocate($im, mt_rand(0,140),mt_rand(0,140),mt_rand(0,140)); imagefilledrectangle($im,0,0,200,60,$white);
      
      





ここで少し明確にする必要があります。 条件付きで白(明るい)と条件付きで黒(暗い)の色を割り当て、その後...はい、はい、フィールド全体でそれらを塗りつぶします。



さらに良いです。 4番目のポイントはテキストです。 斜めにすることができ、いくつかのフォントのいずれかで描画する必要があります。 システムパレットから6個を入力し、次のコードを記述しました。



 $a = mt_rand(-5,5); $s = 40; $f = "captcha_font".mt_rand(1,6).".ttf"; do{ $s--; $b = imagettfbbox ($s, $a, $f, $text); $x = $b[2]-$b[0]; $y = $b[1]-$b[7]; }while(($x>=200)||($y>=60)); $black = imageColorAllocate($im, mt_rand(0,140),mt_rand(0,140),mt_rand(0,140)); imagettftext($im, $s, $a, 100-$x/2, 30+$y/2, $black, $f, $text); imagewave($im);
      
      







はい、どのフォントがどの傾斜とサイズでフレームにぴったり収まるか正確にはわからないため、逆検索法を使用しました。 そして彼は...動作します。 現時点では、次の結果があります。



画像画像



しかし、待って、ImageWave機能とは何ですか? そして、これが歪みの最初の部分です。 ランダムな波を写真に追加します。 一般的には、次のようになります。



 function imagewave($im){ $sx = imagesx($im); $sy = imagesy($im); $dx = mt_rand(0,$sx/2); $xf = mt_rand(-100,100)/20; for($x = 0; $x < $sx; $x++){ $yd = floor(sin(deg2rad($dx+$x)*$xf)*2); $l = array(); for($y = 0; $y < $sy; $y++) $l[$y] = imagecolorat($im,$x,$y); if($yd>0) for($y = 0; $y < $yd; $y++) array_push($l,array_shift($l)); elseif($yd<0) for($y = 0; $y > $yd; $y--) array_unshift($l,array_pop($l)); for($y = 0; $y < $sy; $y++) imagesetpixel($im,$x,$y,$l[$y]); } $dy = mt_rand(0,$sy/2); $yf = mt_rand(-100,100)/20; for($y = 0; $y < $sy; $y++){ $xd = floor(sin(deg2rad($dy+$y)*$yf)*2); $l = array(); for($x = 0; $x < $sx; $x++) $l[$x] = imagecolorat($im,$x,$y); if($xd>0) for($x = 0; $x < $xd; $x++) array_push($l,array_shift($l)); elseif($xd<0) for($x = 0; $x > $xd; $x--) array_unshift($l,array_pop($l)); for($x = 0; $x < $sx; $x++) imagesetpixel($im,$x,$y,$l[$x]); } }
      
      





おそらく私は最速の方法を選択しなかったかもしれませんが、それは以前のように動作します。 そして、使用後のキャプチャは次のようになります。

画像画像



すでにはるかに優れています。 ランダムな角度、ランダムなフォント、同じ色(!)で別のテキスト出力を追加することも決めました。これにより、画像の解析が複雑になります。

画像画像



それだけですか? しかし、違います。 ボットの作業をさらに複雑にするために、私たちは何度か写真を消すことにしました。

 $yd = mt_rand(-30,30); $black = imageColorAllocate($im, mt_rand(0,140),mt_rand(0,140),mt_rand(0,140)); imageline($im,0,$yd,200,30+$yd,$black); imagewave($im); $black = imageColorAllocate($im, mt_rand(0,140),mt_rand(0,140),mt_rand(0,140)); imageline($im,0,30+$yd,200,60+$yd,$black); imagewave($im);
      
      





画像画像



そして最後に、最初に約束したように、花で少し遊んでみましょう。 関数自体とその作業の結果のみを添付します。挿入の呼び出しは問題ないと思います。

 function imagerecolor($im){ $sx = imagesx($im); $sy = imagesy($im); for($x = 0; $x < $sx; $x++){ $rd = mt_rand(80, 120) / 100; $gd = mt_rand(80, 120) / 100; $bd = mt_rand(80, 120) / 100; for($y = 0; $y < $sy; $y++) { $c = imagecolorat($im,$x,$y); $r = (($c >> 16) & 0xFF) * $rd; $g = (($c >> 8) & 0xFF) * $gd; $b = ($c & 0xFF) * $bd; $c = imagecolorallocate($im, $r, $g, $b); imagesetpixel($im,$x,$y,$c); } } }
      
      





画像画像

さて、キャプチャに会社のロゴがなければ幸福とは何ですか? 結果を自分で考えてください。コードは不可能です。

 $l = imagecreatefrompng('../static/image/icon16.png'); imagecopy($im,$l,184,44,0,0,16,16); imagedestroy($l);
      
      





イメージは終わりました-その便利な結論に進みます。



クライアントサーバー



最も簡単な方法は、一部のコード(セッションID、ハッシュ、またはその他の情報)をCookieに保存することです。 しかし、ユーザーが一度に複数の(少なくとも2つの)ウィンドウで作業していて、両方のウィンドウにcaptchaが表示された場合はどうでしょうか。 ここでは、base64でエンコードされた画像のようなスキームの助けになります。 JavaScriptを使用したため、このようなことの結論は非常に単純になりました。



 ob_start(); imagepng($im); $b64 = base64_encode(ob_get_contents()); ob_end_clean(); imageDestroy($im); $response = array('key'=>sha512(md5(strtolower($text)).date('DmyH').get_ip().'RANDOM_SALT'),'img'=>'data:image/png;base64,'.$b64);
      
      





そして、さらにどこかで:

 $response = json_encode($response); ?>Api.callback(<?=$cid?>,<?=$response?>);
      
      





この方法でのフォームの結論も可能です-宿題のためにあなたに任せます。 ;)

ハッシュではソルトを使用し(ソ​​ートの難しさのため)、キャプチャは現在の時間でのみ有効です(ユーザーが完全に不運で、たとえば15:59にキャプチャを受け取り、16:00に入力した場合、動作しません)。 このような画像の出力は、必要な画像のsrcフィールドにフィールド$ response ['img']を代入するだけで実行されます。

ところで、sha512関数:

 function sha512($s){ return hash('sha512',$s); }
      
      







宿題については、ハッシュ内の同様の文字(「0」と「O」、「l」と「I」など)を置き換えることもできます。



今日は以上です。 がんばって。 ;)



All Articles