الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

كيف أمنع إعادة إرسال الفورم بزر التحديث

بدأه JavaPorgrammer في 25 يونيو 2011 · 7 رد · 826 مشاهدة · في منتدى تطوير المواقع بـ PHP
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

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

الإخوة والأخوات الأكارم ..

سؤالي :

عندي صفحة فيها مقال وعليه تعليقات الزوار .. كل شيء ماشي تمام معاي ..

لكن ظهر معي خلل!

عندما أحدث الصفحة تضاف البيانات مرة أخرى إلى قاعدة البيانات!

كيف أمنع إضافة البيانات عند تحديث الصفحة؟

علما أن كود الإضافة بنفس صفحة العرض ..

صفحة عرض البيانات 'كود الإضافة ' :

 if(isset($_POST['send'])){

        require_once './includes/valid-norm-form.inc.php';
        require_once './includes/setData.inc.php';
        require_once './includes/customValid.php';
         $valid = new customValid();
        $valid->check_empty();
        $valid->min_length('name', 3);
        $valid->max_length('name', 15);
        $valid->min_length('content', 10);
        $valid->max_length('content', 500);
        $valid->check_email('email');
        if(!$valid->get_errors()){

            $set = new setData(strip_tags($_POST['content']),  strip_tags($_GET['id'])
                    ,  strip_tags($_POST['name']),  strip_tags($_POST['email']));
     echo '<b style="color:red; font-family:tahoma;">'."شكرا على تواصلك ، سيتم نشر التعليق بعد موافقة المشرف".'</b>';

        }
        else{

           echo '<B style="color:red;">ERRORS ! :</B>';
           $valid->print_errors();

           }}

فئة الاتصال بقاعدة البيانات :

class Connection_db {
    private $host = 'localhost';
    private $user = 'root';
    private $pass = 'root';
    private $db = 'cofee';
    private $con ;
    public function __construct() {
        $this->p_connection();
    }
    protected function p_connection(){
        $this->con = new mysqli($this->host,  $this->user,  $this->pass,  $this->db)
                or die(mysqli_error()) or die(mysqli_connect_error());
        $this->con->set_charset("utf8");
    }
    public function get_connection(){
        return $this->con;
    }
}

فئة الاستعلام :

require 'conn.inc.php';
class setData extends Connection_db{
    private $_comment ;
    private $_content_id;
    private $_email;
    private $_name;
    public function __construct($coment,$content_id,$name,$email) {
        parent::__construct();

        $this->_comment = $coment;
        $this->_content_id= $content_id;
        $this->_name= $name;
        $this->_email = $email;
        $this->insert_comment();
    }
   private function insert_comment(){
        $getCon = parent::get_connection(); 
        $sql = 'insert into commentes (p_name,email,content_id,content_of_comment) values('.  
        "'".$this->_name."','".$this->_email."',".$this->_content_id.",'".$this->_comment."')";
        $result = $getCon->query($sql)  or die(mysqli_error());
        if(!$result){
             echo "ERROR!".mysqli_error();
        }

    }
}

هل من اقتراحات لحل الإشكال؟

لكم مني أعطر التحايا.

عفواً أحبتي انقطاعي بسبب الدراسة دعواتكم بالتوفيق..

{ لا ينال العلم مستحٍ ولا مستكبر }

#2

السلام عليكم..

أولاً أنا لم أقرأ الكود كاملاً، فقط مررت عليه سريعًا.. و لدي ملاحظة قبل الإجابة: من قراءتي السريعة للكود لم ألاحظ - و ربما أنا مخطئ - تنقية الإدخال من أي شيء قد يسبب SQL Injection، و هذه نقطة تستحق الاهتمام إذا كنت فعلاً لم تنقي مدخلات المستخدم تحسبًا للحقن..

ثم بالنسبة للسؤال نفسه، السؤال كما هو حرفيًا، حسب علمي غير ممكن.. لكن هناك حلين يؤديان نفس الغرض إن شاء الله:

الحل الأول: أن تحفظ Session لكل مستخدم فيه وقت آخر تعليق وضعه المستخدم باستخدام دالة time()، و عند محاولة إضافة أي تعليق جديد، يتم المقارنة بين time() الحالي، و المخزن في Session، إذا كان الفرق مثلاً أقل من 60 (أي أقل من 60 ثانية) لا يتم الإرسال.. مع العلم أن Session قد يكون فارغًا إذا لم يكن كاتب التعليق قد وضع تعليقًا في وقت قريب، و وضع هذه الإمكانية في الاعتبار.. أخبرني إذا لم تفهم الاقتراح جيدًا، من فضلك..

الحل الثاني: عند إضافة تعليق، أن تبحث عن أي إرسال سابق بنفس الاسم، و نفس المحتوى، و إذا كنت تريد، يمكن أيضًا اختبار الفرق بين وقت إرسال الأول و وقت إرسال الثاني..

إذا كنت تريد شرح الحلين بالكود، ليس لدي مشكلة، فقط أردت الاختصار، دون وضع أي شيء قد لا يفيد..

1
#3

شاكر لك تفاعلك أخي الكريم

اقتباس

ولاً أنا لم أقرأ الكود كاملاً، فقط مررت عليه سريعًا.. و لدي ملاحظة قبل الإجابة: من قراءتي السريعة للكود لم ألاحظ - و ربما أنا مخطئ - تنقية الإدخال من أي شيء قد يسبب SQL Injection، و هذه نقطة تستحق الاهتمام إذا كنت فعلاً لم تنقي مدخلات المستخدم تحسبًا للحقن..

هو بالفعل كما ذكرت لم أقم بتنقية الإدخال إلا - قضية وسوم الـ html - كما تعرف .. وذلك بدالة الـ striptag ..

في الحقيقة أنا جديد على هذه اللغة ومضطر لبناء موقع بأسرع وقت ممكن + تعلم اللغة أسرع من الممكن :dry:

سأكون ممتنا لك إن زودتني بمراجع عن موضوع الحقن بجمل الـ SQL.

وسأجرب الحلول المذكورة .. مع وافر امتناني وشكري على مساعدتك ووقتك المبذول في قراءة السؤال.

ولي عودة مع النتائج .. بإذن الله.

تحية عطرة لشخصك الكريم.

1

عفواً أحبتي انقطاعي بسبب الدراسة دعواتكم بالتوفيق..

{ لا ينال العلم مستحٍ ولا مستكبر }

#4

السلام عليكم،

أنا من يشكرك أخي، +1 على الرد

بالنسبة للحقن، بالطبع أن تعرف SQL، و بما أنها لغة بسيطة جدًا و تكتب داخل علامات تنصيص في PHP وغيرها من اللغات، فإن ذلك يجعل إمكانية تغيير الكود أمرًا ممكنًا! كيف؟

SELECT Id FROM users WHERE Username='$name' AND Password='$pass'

هذا كود SQL بسيط، تخيل لو أن المدير اسمه admin، و جاء مخترق و أدخل في خانة الاسم admin ثم أدخل في خانة كلمة السر:

' OR 'a'='a

هذا مثال من العديد من الأمثلة على كلمة سر غير حقيقية يدخلها مخترق، و هناك أمثلة كثيرة، إذا أدخل المخترق هذه في كلمة السر، و أدخل اسم المدير، سيصبح الاستعلام كالتالي:

SELECT Id FROM users WHERE Username='admin' AND Password='' OR 'a'='a'

و بما أن a = a طبعًا، سيستطيع المخترق المرور دون كلمة السر!

كيف نمنع ذلك؟ هناك دوال في PHP تختص بمنع هذا الحقن، أفضلها - بالنسبة لـMySQL - أن تستخدم دالة mysql_real_escape_string، و لكنها تتطلب اتصال بقاعدة بيانات لتعمل..

ماذا تفعل هذه الدالة؟ كل ما تفعله هو وضع Backslash قبل أي علامة قد تغير الاستعلام، مثل ' لتصبح

\'

و هكذا، لا يتأثر الاستعلام، هناك نقطة أخرى،، HTML escaping لمن ثغرات XSS يفضل أن يتم أثناء إعادة المحتوى للزائر، لا أثناء حفظه في قاعدة البيانات، لأنه لن يضر قاعدة البيانات، و لكن سيغير المحتوى الذي فيها..

كذلك، strip_tags ليست كافية، يعني إذا أردت أن أسمي نفسي مثلاً <hello> هل تصبح hello فقط! لماذا؟

الاختراق ربما يأتي بشكل غريب حقًا، مثل أن تتيح للزائر أن يضع رابط صورة فيضع هو:

javascript: alert('XSS');

هكذا سيتم إدخال كود جافاسكريبت في الصفحة!

لمنع هذا نستبدل أيضًا الأقواس، لكن لحظة إظهار الشيء من قاعدة البيانات..

و نستخدم دالة htmlspecialchars

مراجع:

دالة htmlspecialchars - لا تنسى أن تضع في المدخل الثاني ENT_QUOTES لتحويل علامات التنصيص الفردية و الزوجية، و وضع ترميز الصفحة في المدخل الثالث، و لا تنسى استبدال الأقواس

( 	->   	& #40;
) 	->   	& #41;

* دون المسافة بعد &

، إذا كنت ستجعل الزائر يدخل رابط مثلاً..

SQL Injection - اعذرني لم أتذكر أي روابط أفضل حاليًا، لذا شرحته مختصرًا بنفسي! لا تنسى استخدام دالة mysql_real_escape_string بعد الاتصال بقاعدة البيانات..

أتمنى أني استعطعت إفادتك..

نسيت: شيء أخير، أهم أهم شيء من أجل الحماية، أن تتحقق من كل مدخلات الزائر، إذا طلبت العمر، تأكد أن ما أدخل هو رقم، إذا طلبت البريد الإلكتروني يجب أن يكون بريدًا حقًا، إذا طلبت رابطًا يجب أن يكون أدخل بريدًا أيضًا.. لا تثق في الزائر ثقة كاملة أبدًا.. فما المخترق إلا زائر!!

تم تعديل هذه المشاركة بواسطة sitesmaker في 26 يونيو 2011 في 09:27

1
#5

عليكم السلام أخي الحبيب..

أشكرك جزيل الشكر على تفاعلك المميز ..

فعلا معلومات قيمة جدا ! وتهمني كثيرا!

+1 < ولو استطعت أكثر من هذا لفعلت! :blush:

لسى بدأت بالقراءة في هذا المووضوع .. وأحتاج المزيد من المراجع ..

قمت بإعطاء كل فورم معرف خاص به عن طريق الدالة : uniqid

 $_id = sha1(uniqid(rand(),true));
    $_SESSION['_id']=$_id;

وتضمينه داخل الفورم ليتم التأكد من عدم تطابق المعرف مع المتغير في الـ SESSION في حالة إعادة إرسال الفورم.

if(isset($_SESSION['_id'])){
     (if(strcasecmp($id,$_SESSION['_id'])===0){
unset($_SESSION['id']);
}}

طبعا الكود مختصر :)

عفواً أحبتي انقطاعي بسبب الدراسة دعواتكم بالتوفيق..

{ لا ينال العلم مستحٍ ولا مستكبر }

#6

أخي

بخصوص الحماية من الفلوود,

قم باستخدام captcha

فهي تحميك من السبام والفلود

وبذلك رح تريح بالك

لو لم تعرف ماهي الـ captcha

هي تلك الصورة التي تجدها في التسجيل في المواقع العديدة

فيها حروف ورموز

وفي بعض الناس يسمونها "التحقق البشري" حيث ان الآلة تعجز عن قرائة مابداخل الصورة

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

1
#7

كلامك صحيح أخي عبدالمنعم ..

فكرة قائمة في بالي :)

أشكرك.

+1

عفواً أحبتي انقطاعي بسبب الدراسة دعواتكم بالتوفيق..

{ لا ينال العلم مستحٍ ولا مستكبر }

#8

العفووو وبالخدمة :)

مواضيع مشابهة

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…