التغطية المصورة ليوم سوالف: الجزء الأول، الجزء الأخير
الفائزون في المسابقة الأصغر لسوالف كاست

 

العودة   سوالف سوفت > قسم تطوير وبرمجة المواقع للمتقدمين > PHP
المدوّنات البحث مشاركات اليوم اجعل كافة المشاركات مقروءة

رد  
 
LinkBack أدوات الموضوع
عضو نشيط
تاريخ التسجيل: May 2007-
#1 (permalink)  
إحمي موقعك من الأوامر المزعجة و حارب ارتفاع الــ load


باسم الله الرحمان الرحيم
قُل لِلَّذِينَ كَفَرُواْ إِن يَنتَهُواْ يُغْفَرْ لَهُم مَّا قَدْ سَلَفَ وَإِنْ يَعُودُواْ فَقَدْ مَضَتْ سُنَّةُ الأَوَّلِينِ
سورة الأنفال الآية 38
السلام عليكم و رحمة الله و بركاته
لا يخفى على أصحاب / مبرمجي المواقع الخطر الكبير الذي يشكله تنفيذ عملية مكلفة للسيرفر بشكل مفرط في التكرار و خاصة إذا كانت العملية مرتبطة بقاعدة البيانات.
في كثير من الحالات تعتبر هده العملية ثغرة قاتلة يمكن من خلالها اختراق الموقع بالكامل . و في أفضل الأحوال تعليق الموقع مؤقتا بسبب ارتفاع الضغط load على السيرفر

مثلا في برنامج المنتديات vbulletin تسمح لوحة التحكم للمشرف العام تحديد مدة معينة لكل عملية بحت . بحيث يمكن للمشرف العام منع الزائر / العضو من إنجاز أكتر من عملية بحت خلال 20 ثانية . و ما كل هدا إلا بسبب وعي مبرمجي vbulletin بخطورة العملية

لهدا أقترح عليكم في هدا الموضوع التعرف على أسهل طريقة لحماية الموقع من الأوامر المزعجة (spam)
التطبيق سيكون على بيئة البرمجة php و باعتماد قاعدة بيانات mysql . و بإمكان المبرمجين الدين يعتمدون على بيئة برمجية مختلفة استخلاص الفكرة و تطبيقها حسب خبرتهم

فعلى بركة الله نبدأ
أولا سنحتاج لجدول في قاعدة البيانات لتسجيل جميع العمليات التي يتم تنفيذها على الموقع و افتراضيا ستكون الحقول المطلوبة هي :
id: رقم العملية
type: نوع العملية : (بحت . إرسال موضوع . تحميل ملف ....)
awner: الفاعل - سيكون هو اسم المستخدم إدا كان مسجلا و يتم استخراجه من الجلسة
أما إدا كان المستخدم غير مسجل فيمكنك استخدام كود التحقق captcha (رابط الدرس) لتفادي الإغراق
time: وقت تنفيذ العملية
حسب ما سبق ستكون بنية الجدول هي :
كود:
CREATE TABLE `antiload` (
`id` INT( 100 ) NOT NULL AUTO_INCREMENT ,
`type` VARCHAR( 100 ) NOT NULL ,
`awner` VARCHAR( 100 ) NOT NULL ,
`time` VARCHAR( 100 ) NOT NULL ,
UNIQUE (
`id` 
)
) ENGINE = MYISAM ;

هدا مع اعتبار أن antiload هو اسم الجدول


الآن . كيف يتم تسجيل العمليات؟
مباشرة بعد تنفيذ أي عملية يتم تنفيذ استعلام إلى قاعدة البيانات يملأ الحقول في جدول antiload

لنفترض أن العملية التي تم تنفيذها هي: البحت
على سبيل المثال
كود PHP:
 
$search 
$_POST['search'];
$lo=mysql_query("select * from topic where topic='%$search%'"); 
مباشرة بعد هده العملية ننفذ افتراضيا الاستعلام التالي

كود PHP:
if($lo){
mysql_query("INSERT INTO antiload(type,awner,time)VALUES('search','$user','$time')");

لا أضن أنني في حاجة لتوضيح مصدر المتغيرات التي استخدمتها في الاستعلام الأخير
أما $lo فهو المتغير المرتبط بتنفيذ عملية البحت و قد قمنا بربطه بعملية البحت الأولى و تمريره إلى الدالة الشرطية if في الكود الأخير بحيث لا يتم إدخال المعلومات إلى جدول antiload إلا في حالة تحقق الشرط

إدا تم تنفيذ العملية بنجاح فمن المفترض أن نجد التالي في الجدول الذي أنشأناه


الآن تم إدخال المعلومات إلى الجدول
تبقى أمامنا الخطوة الحاسمة و الأهم و هي :
كيف نستثمر هده المعلومات في منع الإغراق (spam)
نبقى مع المثال الأول : ( البحت )

كود PHP:
$search $_POST['search'];
$lo=mysql_query("select * from topic where topic='%$search%'"); 

قبل تنفيذه مباشرة علينا التحقق من أن المستخدم لم يقم بعملية مشابهة مند 20 ثانية
كيف؟
نحدد وقتا أقدم من التاريخ الحالي بـ 20 ثانية . و الطريقة معروفة :

كود PHP:
$Lasttime time()-20
بعد حصولنا على المتغير $Lasttime يتوجب علينا الرجوع إلى قاعدة البيانات بالاستعلام التالي :
هل تم إنجاز عملية بحت بعد الوقت $Lasttime من طرف نفس المستخدم؟



كود PHP:
$result=mysql_query("SELECT type, awner, time FROM antiload WHERE type='search' and awner='$user' and time>'$Lasttime'"); 
هدا سيعطينا عمليات البحت التي قام بها نفس المستخدم خلال فترة لا تزيد عن 20 ثانية.
لنحسب عددها عن طريق دالة mysql_num_rows()

كود PHP:
$count=mysql_num_rows($result); 
ادا كان عدد عمليات البحت التي تم إنجازها أكبر من 0 فينبغي منع المستخدم من تكرار العملية عن طريق دالة إيقاف التنفيذ die()


كود PHP:
if($count>0){
die(
"عفوا . لا يمكنك إنجاز أكتر من عملية بحت في أقل من 20 ثانية");


في المرفقات متال جد مبسط لصفحة لا يمكنك اعادة طلب محتواها الا بعد مرور 20 تانية

في حالة نقل الموضوع يرجى دكر المصدر

و السلام عليكم






الملفات المرفقة
نوع الملف: zip antiload.zip‏ (762 بايت, المشاهدات 96)
__________________
a000a.uni.cc
Maximum file size : 2 mb
جميع الامتدادات متاحة بدون استتناء
--------------------
[نقاش] : أساسيات برمجة منتدى
azizsoft غير متواجد حالياً   قديم 24-04-2008, 02:32 AM
رد مع اقتباس
Moderator
تاريخ التسجيل: Aug 2004-
#2 (permalink)  

السلاام عليكم، هذا نقاش .. فارجوا من الاخ azizsoft ان لا يزعل مني
انا بصراحه ضد الخطوه
كود PHP:
mysql_query("INSERT INTO antiload(type,awner,time)VALUES('search','$user','$time')"); 
لانك الان تضع معلومه زائده في قاعده البيانات. وكما تعرف الكتابه في قاعده البيانات يأخذ وقت اكبر من القرائه، وايضا عندما يكون العضو منتسب لمده 4 او 5 سنوات وبحث اكثر من 1000 مره، فستفعل ضغط لقاعده البيانات في حين البحث عن المعلومه التي تريدها.

طبعا لن اقول رأيي بدون اي اقتراحات! .. وهذه هي اقتراحاتي..
1- اذا اردت الاصرار على استخدام طريقتك .. ففعل التالي .. قم بوضع الاندكس المناسب .. وضعه بالذات على الtime .. هذا سيجعل البحث اسرع بمالا يقل عن 700%.. ايضا لا تنسى ان تضع cronjob لكي يمسح الجدول من محتواها في كل يوم .. هذا سيوفر لك مساحه و قوه معالجه

فغير تركيب الجدول من
كود:
CREATE TABLE `antiload` (
`id` INT( 100 ) NOT NULL AUTO_INCREMENT ,
`type` VARCHAR( 100 ) NOT NULL ,
`awner` VARCHAR( 100 ) NOT NULL ,
`time` VARCHAR( 100 ) NOT NULL ,
UNIQUE (
`id` 
)
) ENGINE = MYISAM ;
كود:
CREATE TABLE IF NOT EXISTS `antiload` (
  `id` int(100) NOT NULL auto_increment,
  `type` varchar(100) NOT NULL,
  `awner` varchar(100) NOT NULL,
  `time` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  PRIMARY KEY  (`id`),
  KEY `time` (`time`)
) ENGINE=MyISAM;
وبدون استخدام الامر
كود PHP:
mysql_query("INSERT INTO antiload(type,awner,time)VALUES('search','$user','$time')"); 
استخدم

كود PHP:
mysql_query('SET @a = (SELECT id FROM `antiload` as `temp` WHERE `awner` = "'$user'" LIMIT 1);
UPDATE `antiload` SET `time` = NOW() where id = @a;
'

والباقي .. اتبع نفس خطوات الاخ azizsoft

2- اما الحل المجنون .. اللذي لن يقتل السرفر حتى وان كان هناك هجوم على قاعده البيانات .. هو باستخدام خواص الfull-text search الموجوده في MySQL4 والاصدارت التي بعدها . مع العلم ان الMySQL4 صدر قبل قرابه ال4 سنوات






__________________
هلابي افضل المواقع العربية تصميماً
انصح باستخدام ابونتو
hilaby غير متواجد حالياً   قديم 24-04-2008, 08:48 AM
رد مع اقتباس
مشرف قسم PHP
تاريخ التسجيل: Apr 2002-
#3 (permalink)  

تستخدم هذه الطرق في تقنين دعونا نسميها العمليات المكلفه ... وهي غالبا البحث , كتابة موضوع جديد , كتابة رد جديد هي طريقة جدا مفيده في حالة كون لديك زوار كثيرين في نفس الوقت .
لماذا مكلفه لانها تستهلك موارد من النظام ليس لكون هناك خطأ برمجي مثلا عدم اضافة index ولكن لكون طبيعتها هكذا .

hilaby ملاحظتك في محلها لكن هناك حل لها ... ان تنفذ عملية حذف لجميع العمليات التى انتهت مدتها ... اي ان عمر كل عملية هو 20 ثانيه ... اذا سوف ننفذ هذا الاستعلام قبل عملية ادخال العملية الجديده
كود:
DELETE FROM `antiload ` WHERE time< $Lasttime
وبهذه تكون تخلص من جميع السجلات التى انتهت فترتها .






__________________
I Love PHP (d4d@hotmail.com)
http://www.daif.net/
daif غير متواجد حالياً   قديم 24-04-2008, 12:25 PM
رد مع اقتباس
Jeddah Bikers
تاريخ التسجيل: Jan 2008-
#4 (permalink)  

يعطيكم العافية معلومات فعلا مفيدة






انشر غير متواجد حالياً   قديم 24-04-2008, 12:43 PM
رد مع اقتباس
عضو نشيط جدا
تاريخ التسجيل: May 2007-
#5 (permalink)  

نقاش جميل جدا ووجهات نظر اجمل ...

اعتقد اخواني انو لا بد من هالخطوة وكلام الاخ hilaby صحيح ومعقول ... لكن ما ننكر انو الاخ عزيزسوفت فكر وما بخل علينا بالمعلومات الجديدة يعطيكم العافية جميعا مبدعين ...

الى الامام اخواني .






EbNCaNa غير متواجد حالياً   قديم 24-04-2008, 06:24 PM
رد مع اقتباس
عضو نشيط
تاريخ التسجيل: May 2007-
#6 (permalink)  

hilaby

كلامك سليم 100 بالمئة

اقتباس:
..قم بوضع الاندكس المناسب .. وضعه بالذات على الtime .. هذا سيجعل البحث اسرع بمالا يقل عن 700%.. ..
لم أنتبه لهدا الأمر ما شاء الله عليك

اقتباس:
ايضا لا تنسى ان تضع cronjob لكي يمسح الجدول من محتواها في كل يوم .. هذا سيوفر لك مساحه و قوه معالجه
نسيت أن أوضح في الدرس كيفية المسح الدوري للسجلات القديمة
و هو نفس ما دكره الأخ daif


بالنسبة لتغير الاستعلام من الادخال الى التحديت اعتقد أن المسح الدوري مع الاحتفاض بالطريقة التي شرحتها أفضل لأنها أقل تعقيدا و الله أعلم


اقتباس:
2- اما الحل المجنون .. اللذي لن يقتل السرفر حتى وان كان هناك هجوم على قاعده البيانات .. هو باستخدام خواص الfull-text search الموجوده في MySQL4 والاصدارت التي بعدها . مع العلم ان الMySQL4 صدر قبل قرابه ال4 سنوات
لم أسمع بهدا من قبل . سأحاول البحث في الموضوع






__________________
a000a.uni.cc
Maximum file size : 2 mb
جميع الامتدادات متاحة بدون استتناء
--------------------
[نقاش] : أساسيات برمجة منتدى

التعديل الأخير تم بواسطة : azizsoft بتاريخ 24-04-2008 الساعة 09:17 PM.
azizsoft غير متواجد حالياً   قديم 24-04-2008, 09:15 PM
رد مع اقتباس
عضو نشيط
تاريخ التسجيل: May 2007-
#7 (permalink)  

شكرا لكل من رد على الموضوع






__________________
a000a.uni.cc
Maximum file size : 2 mb
جميع الامتدادات متاحة بدون استتناء
--------------------
[نقاش] : أساسيات برمجة منتدى
azizsoft غير متواجد حالياً   قديم 24-04-2008, 09:19 PM
رد مع اقتباس
عضو نشيط
تاريخ التسجيل: Feb 2008-
#8 (permalink)  

السلام عليكم ورحمة اللة وبركاتة

اخ hilaby ياريت توضحلى بعض الاشياء فى هذا الاستعلام

mysql_query('SET @a = (SELECT id FROM `antiload` as `temp` WHERE `awner` = "'$user'" LIMIT 1);
UPDATE `antiload` SET `time` = NOW() where id = @a;')

ما فائدة هذة العبارة فى بداية الاستعلام @a ونهايتة

وسوال اخر هل NOW() فى الاستعلام تعنى الوقت اليونكس ومثل الدالة
time();







التعديل الأخير تم بواسطة : tech بتاريخ 25-04-2008 الساعة 12:11 AM.
tech غير متواجد حالياً   قديم 25-04-2008, 12:10 AM
رد مع اقتباس
عضو نشيط
تاريخ التسجيل: Aug 2007-
#9 (permalink)  

مشكور اخوي azizsoft على الدرس المميز
ومشكورين الاخوه hilaby و daif على المداخلات الرائعة


ولاكن عندي سؤال بخصوص الload

هذا رابط قسم الphp في منتديات سوالف
PHP - سوالف سوفت

لو غيرناه الى

PHP - سوالف سوفت

سيقوم بعرض 200 موضوع بدلا من المواضيع التي محددها المسؤول عن المنتدى

فهل هذه العملية تزيد الضغط على الموقع

والسلام عليكم






عقل الكمبيوتر غير متواجد حالياً   قديم 25-04-2008, 03:45 PM
رد مع اقتباس
Moderator
تاريخ التسجيل: Aug 2004-
#10 (permalink)  

الاخ tech
العلامه @ قبل اي كلمه تعني متغير مثل الPHP يستخدم العلامه $ ..
فمعنى الاستعلام .. ضع الid الناتج من العمليه WHERE `awner` = $user في المتغير a@ لكي تستخدمه في الاستعلام التالي.

اما ()NOW .. هي ترمز الى الان .. هي داله في الMySQL تعرجع الوقت الحالي كناتج






__________________
هلابي افضل المواقع العربية تصميماً
انصح باستخدام ابونتو
hilaby غير متواجد حالياً   قديم 26-04-2008, 05:14 AM
رد مع اقتباس
عضو نشيط
تاريخ التسجيل: Feb 2008-
#11 (permalink)  

اخى hilaby شكرا لك على التوضيح






tech غير متواجد حالياً   قديم 26-04-2008, 10:15 PM
رد مع اقتباس
عضو نشيط
تاريخ التسجيل: Apr 2008-
#12 (permalink)  

بارك الله فيك, موضوع اكثر من رائع






menokia غير متواجد حالياً   قديم 28-04-2008, 08:52 AM
رد مع اقتباس
عضو فعال
تاريخ التسجيل: May 2006-
#13 (permalink)  

نقاش رائع وجميل

ومنكم نستفيد

ضيف الله ، هلابي ، عزيز

وجميع من شارك
شكرا لكم .

اخوكم وحيد .






الإمبراطور وحيد غير متواجد حالياً   قديم 30-04-2008, 12:33 AM
رد مع اقتباس
عضو نشيط
تاريخ التسجيل: Aug 2007-
#14 (permalink)  

بالفعل نقاش أكثر من رائع
كل رد زياده .. يتضح الأمر أكثر لمن لا يعلم
بارك الله فيكم






عاشق الصداقه غير متواجد حالياً   قديم 06-05-2008, 09:21 AM
رد مع اقتباس
رد


 

أدوات الموضوع

تعليمات المشاركة
لا تستطيع كتابة مواضيع
لا تستطيع كتابة ردود
لا تستطيع إرفاق ملفات
لا تستطيع تعديل مشاركاتك

كود [IMG] متاحة
كود HTML معطلة
Trackbacks are متاحة
Pingbacks are متاحة
Refbacks are متاحة


المواضيع المتشابهه
الموضوع كاتب الموضوع المنتدى مشاركات آخر مشاركة
دليلك كيف تشهر موقعك على الإنترنت wael2 تطوير الويب 16 15-10-2005 01:11 AM
بلش الشغ شباب wael2 تطوير الويب 2 12-12-2003 10:46 AM
مشكله اخلاقيه (مطلوب رأيكم) LATE قسم تبادل خبرات الاستضافة 30 12-05-2003 04:53 AM
سلسلة كيف ( 4 ) : كيف يكون تصميم موقعك متقناً ؟!! رضا تطوير الويب 19 21-04-2003 12:12 PM


الساعة الآن: 09:58 AM بتوقيت المملكة العربية السعودية