طاب مسائك! على الرغم من عنوان المقال ، فإنه سيقدم الأساليب والوظائف العامة التي استخدمتها لإنشاء كلمة التحقق الخاصة بي ، والتي يمكن تطبيقها في أطر أخرى مع الحد الأدنى من التغييرات. تستند بعض الوظائف والأساليب على مواد مركز تطوير DIY CAPTCHA .المقدمة
للعمل مع الصور ، تحتاج إلى التحقق من وجود مكتبة GD في PHP. يمكن القيام بذلك باستخدام دالة gd_info (). في الأمثلة المقدمة ، أستخدم الإصدار 2.1.0 و PHP 7.4.3 ، وهو غير ضروري في هذه الحالة ، حيث لا يتم استخدام وظائف PHP7.المنطق
ما كلمة التحقق التي أريد رؤيتها؟ واحد سيساعدني على تقليل عدد طلبات الخادم أثناء التفويض في موقعي باستخدام برنامج Codeigniter 4.للتطبيق ، سيتم إنشاء الصورة التي تحتوي على الرمز حصريًا على جانب الخادم ، وحفظها في مجلد مؤقت ، وترميزها في base64 وإعادتها إلى المستخدم.تطوير
قبل رسم الصورة ، نكتب طريقة توليد الكود.public function generate_code() {
srand((float) microtime() * 1000000);
$chars = 'ABDEFHKNRSTYZabdefhknrstyz23456789';
$length = rand(5, 7);
$numChars = strlen($chars);
$str = '';
for ($i = 0; $i < $length; $i++) {
$str .= $chars[rand(0, $numChars - 1)];
}
$array_mix = preg_split('//', $str, -1, PREG_SPLIT_NO_EMPTY);
shuffle($array_mix);
delete_cookie('cap');
set_cookie('cap', md5(implode("", $array_mix)), self::$_code_time);
return implode("", $array_mix);
}
ألاحظ أنه في المستقبل سأستخدم خطوطًا مختلفة لعرض الأحرف ، لذلك عليك الانتباه إلى مجموعة الأحرف الأصلية ، أو إلى الخطوط نفسها ، من أجل تجنب المشاكل مع أحرف مثل "Z" و "z" و "X" و "x" ، "I" و "l" ، وما إلى ذلك ، لأن تشويه الصورة يمكن أن يجعل إدخال كلمة التحقق مشكلة.أعلن المجالات الضرورية في المستقبل.public static $width = 220;
public static $height = 120;
public static $fonts_num = 4;
private static $_code_time = 180;
أقوم بإعداد بعض الطرق لتوليد الخلفيات والضوضاء (القائمة الكاملة في النهاية).
private function _add_line($img, $mode = '', $max = 100) {
for ($i = 0; $i < rand(0, $max); $i++) {
$color = imagecolorallocate($img, rand(80, 150), rand(80, 150), rand(80, 150));
if ($mode === 'parallel') {
$r1 = rand(0, self::$width);
$r2 = rand(0, self::$width);
imageline($img, $r1, $r1, $r2, $r1, $color);
imageline($img, $r1, $r2, $r1, rand(0, 220), $color);
} else {
imageline($img, rand(0, self::$width), rand(0, self::$width), rand(0, self::$width), rand(0, self::$width), $color);
}
}
}
private function _add_poly($img) {
$points = [];
for ($i = 0; $i < 10; $i++) {
array_push($points, rand(0, self::$width * 2));
}
$color = imagecolorallocate($img, rand(80, 190), rand(80, 190), rand(80, 190));
imageFilledPolygon($img, $points, 5, $color);
}
private function _set_glitch_color($image, $xn = 0, $yn = 0, $mode = 'normal') {
$start = rand(self::$height / 2, self::$height / 2 - self::$height / 4);
$finish = $start + rand(5, 15);
for ($x = 0; $x < self::$width - 1; $x++) {
for ($y = 0; $y < self::$height - 1; $y++) {
if ($mode != 'normal') {
$xn = rand(0, 1);
$yn = rand(0, 1);
} else {
$finish = $start + 3;
}
if ($y > $start && $y < $finish) {
imagesetpixel($image, $x + $xn, $y + $yn, imagecolorat($image, $x, $y));
}
}
}
}
جاهزة تقريبا. نكتب الرمز السري في الصورة.private function _add_text($img, $text) {
$x = rand(10,20);
for ($i = 0; $i < strlen($text); $i++) {
$text_color = imagecolorallocate($img, rand(150, 250), rand(150, 250), rand(150, 250));
imagettftext($img, rand(35, 40), rand(0, 10) - rand(0, 10), $x, rand(55, 95), $text_color, 'fonts/' . rand(1, self::$fonts_num) . ".ttf", $text[$i]);
$x += rand(25, 35);
}
}
نحن نجمع بين الطرق الجاهزة لإنشاء صورة والتحقق من الرمز.public function img_code($code) {
$image = imagecreatetruecolor(self::$width, self::$height);
imageantialias($image, true);
$rand_color = imagecolorallocate($image, rand(50, 120), rand(50, 120), rand(50, 120));
imagefilledrectangle($image, 0, 0, self::$width, self::$height, $rand_color);
$this->_add_rand_bg($image);
$this->_add_text($image, $code);
$this->_add_glitch($image, 'normal');
$this->_add_glitch($image, 'boom');
$this->_add_line($image, 'rand', 200);
$file = 'temp/' . md5($code) . ".png";
imagepng($image, $file);
imagedestroy($image);
$res = base64_encode(file_get_contents($file));
unlink($file);
return $res;
}
public function check($tested) {
$cap = get_cookie('cap');
$r['error'] = '';
if (!$cap) {
$r['error'] = ' .';
} elseif (strcmp($tested, $cap)) {
$r['error'] = ' .';
}
delete_cookie('cap');
return $r;
}
باستخدام
في وحدات التحكم اللازمة ، نقوم بإعداد اختبار CAPTCHA على النحو التالي:public function __construct() {
...
$this->captcha = new \App\Libraries\Captcha();
...
}
public function some_function() {
...
$data['captcha'] = $this->captcha->img_code( $this->captcha->generate_code() );
return view('page/template', $data);
}
public function recaptcha(){
return $this->captcha->img_code( $this->captcha->generate_code() );
}
في القالب ، قم بإنشاء رمز مميز وزر لإعادة إنشاء الصورة:...
<input type="hidden" name="<?= csrf_token() ?>" value="<?= csrf_hash() ?>" id="csrf"/>
...
<img src="data:image/png;base64,<?= $captcha ?>" id="cap" width="220" height="120"/>
<div id="ref" onclick="recaptcha()">⥁</div>
...
نضيف مسار لطلب اجاكس.$routes->post('/recap', 'AuthController::recaptcha');
وأجاكس نفسها.var numlog = 0;
function recaptcha() {
if(numlog <= 5){
$.ajax({
type: 'post',
url: '/recap',
data: {csrf_token: $('#csrf').val()},
success: function (result) {
numlog++;
$('#cap').attr('src', "data:image/png;base64," + result + '');
}
});
}else{
$('#ref').css('display', 'none');
}
}
مجموع
تعمل لوحة الألوان الصاخبة ومجموعة التشوهات ذات المعلمات المختلفة على تعقيد حل اختبار CAPTCHA بشكل كبير. بعد اللعب مع الثوابت ، يمكنك الحصول على نتائج مختلفة.راجعت جميع النتائج في محرر رسومي من خلال رمي عتبة على الصور ، وبالتالي تسليط الضوء على الشخصيات التي يمكن استخدامها للتعرف عليها.
الضوضاء والخطوط العشوائية ، بالطبع ، تزيد من التعقيد. لكن الاستنتاج الذي توصلت إليه هو ما يلي: إذا لزم الأمر والمرغوب فيه ، فإن هذا الحل ليس آمنًا تمامًا ، ومع ذلك ، فهو يساعد في الحماية من الروبوتات العادية.يمكن الاطلاع على الرمز الكامل على جيثب . سأكون سعيدا لسماع التوصيات والتعليقات.