php MySql إنشاء فضاء للأعضاء

استمارات التسجيل و الدخول و الخروج

آخر تحيين: 13-12-2015

كلمة المرور بين التشفير و السرقة php رفع الملفات


حتّى نُتيح للزوار إمكانية فتح حساباتهم ليصبحوا أعضاء على موقعنا ، سنحتاج إلى ما يلي :

  • blog_users : جدول في قاعدة البيانات لتخزين معطيات الأعضاء الجدد
  • registration.php : صفحة لتسجيل الأعضاء الجدد
  • login.php : صفحة الدخول أو ربط الإتصال
  • logout.php : صفحة الخروج و تدمير بيانات الجلسة

من باب التنظيم أقترح عليكم وضع الصفحات الثلاث ، داخل ملف جديد ، سنسمّيه مثلا : "members"

جدول "blog_users"

CREATE TABLE IF NOT EXISTS `blog_users` (
  `user_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `user_name` varchar(70) NOT NULL,
  `user_email` varchar(255) NOT NULL,
  `user_password` varchar(255) NOT NULL,
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;

ما أنصحكم به هو ترك عدد مكونات النص "varchar(255)" في حقلي البريد الإلكتروني و كلمة المرور كما هي . بالنسبة للبريد الإلكتروني ، يجب احترام معايير RFC5321 و RFC5322 التي تسمح للبريد أن يصل إلى 254 مُكوّناً . أمّا بالنسبة لكلمة المرور ، لمراعاة التشفير المستعمل مستقبلا من باب الإحتياط اخترنا أيضا 255 مُكوّنا . على كل حال سنرى هذا بتفصيل لاحقا .

registration.php

هذه الصفحة ستضم استمارة لتسجيل الأعضاء الجدد مع معالجة بياناتها .
الإستمارة :
عندما يُقرّر الزائر أن يصبح عضوا في موقعكم ، أول خطوة وجب عليه القيام بها ، هي ملأ استمارة التسجيل . تحتوي هذه الإستمارة مجموعة من البيانات حول العضو ، مثل : إسمه و بلده و جنسه و تاريخ ميلاده و بريده الإلكتروني و كلمة مروره ...إلخ . سنكتفي بالحقول الأساسية و الضرورية لإنشاء استمارة التسجيل ، يمكنكم دائما إضافة أي حقل آخر حسب حاجتكم ، فقط تذكّروا بأن أغلب الزوار يملّون من ملأ استمارات طويلة تحتوي على الكثير من البيانات . لهذا سنكتفي حاليا بالحقول الأساسية لإنشاء استمارة التسجيل :
- pseudo : إسم المستخدم
- email : عنوان البريد الإلكتروني
- pass : كلمة المرور
- pass_confirm : تأكيد كلمة المرور . هذا الحقل كما لاحظتم ليس موجودا في الجدول السابق ، لأننا لن نقوم بتخزينه في قاعدة البيانات . الغرض منه هو مقارنته أثناء المعالجة مع حقل كلمة المرور ، للتأكد من أن المستخدم لم يقترف خطأ بالسهو أثناء كتابة كلمة المرور . يمكنكم إضافة حقل أيضا لتأكيد البريد الإلكتروني ، إذا رغبتم في ذلك .

<h1>استمارة التسجيل</h1>
  <form action="" id="form" method="post" >
    <fieldset class="form-item"><legend>التسجيل</legend>
        <label for="pseudo">الإسم</label>
            <input  type="text" name="pseudo" id="pseudo"><br>
        <label for="email">البريد الإلكتروني</label>
            <input type="email" name="email" id="email"><br>
        <label for="pass">كلمة المرور</label>
            <input type="password" name="pass" id="pass"><br>
        <label for="pass_confirm">تأكيد كلمة المرور</label>
            <input type="password" name="pass_confirm" id="pass_confirm"><br>
	</fieldset>

	<fieldset class="form-submit">
        <input type="submit" name="submit" value="موافق" class="button green">
	</fieldset>
</form>

تخزين معطيات الإستمارة في قاعدة البيانات:
سنبدأ أوّلا بالسكريبت المبدئي لتخزين البيانات في القاعدة .مع عدم نسيان ربط الإتصال بقاعدة البيانات (عدلوا البيانات حسب حاجتكم)

<?php
try 
{
  $db = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
} 
catch(PDOException $e)
{
  die('خطأ:'. $e->getMessage());
}
?>

من العملي أن تكون شيفرة ربط الإتصال في صفحة مستقلة ، سنسميها "db-connection.php" مثلا و سنقوم بإقحامها متى نريد استعمال قاعدة البيانات .
ستصبح لدينا صفحة registration.php مع إضافة الإستمارة ، كالتالي :

registration.php

<?php 
require '../includes/header.php';
require '../includes/db-connection.php';

if (isset($_POST['submit']))
{
  $user  = $_POST['pseudo'];
  $email = $_POST['email'];
  $password = $_POST['pass'];
  $pass_confirm = $_POST['pass_confirm'];

// معالجة البيانات 
// ...
// إدخال البيانات في القاعدة
  $stmt= $db->prepare('INSERT INTO blog_users (user_name, user_email, user_password) 
              VALUES (:name, :mail, :pass)
            ');
    $stmt->bindValue(':name',$user,PDO::PARAM_STR);
    $stmt->bindValue(':mail',$email,PDO::PARAM_STR);
    $stmt->bindValue(':pass',$password,PDO::PARAM_STR);
    $stmt->execute();

    $stmt->CloseCursor();

    // تعيين جلسة لإشعار المستخدم بنجاح عملية تسجيله ، ثم تحويله لصفحة الدخول
    $_SESSION['message'] = htmlspecialchars($user). ' : تم تسجيلك بنجاح ، يمكنك الولوج لحسابك عبراستمارة الدخول أسفله : ';
    header('location:login.php'); exit;
}
?>
<form action="" id="form" method="post" >
    <fieldset class="form-item"><legend>التسجيل</legend>
        <label for="pseudo">الإسم</label>
            <input  type="text" name="pseudo" id="pseudo"><br>
        <label for="email">البريد الإلكتروني</label>
            <input type="email" name="email" id="email"><br>
        <label for="pass">كلمة المرور</label>
            <input type="password" name="pass" id="pass"><br>
        <label for="pass_confirm">تأكيد كلمة المرور</label>
            <input type="password" name="pass_confirm" id="pass_confirm"><br>
	</fieldset>

	<fieldset class="form-submit">
        <input type="submit" name="submit" value="موافق" class="button green">
	</fieldset>
</form>
<?php
require '../includes/footer.php';

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

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


login.php

بما أننا أتحنا للأعضاء فتح حساباتهم على موقعنا . يجب أن نوفر لهم إمكانية ربط الإتصال عبر استمارة الدخول . حتى يتمكنوا من الإستفادة من مزايا خاصة .
استمارتنا ستتضمن حقلين حاليا :
ـ حقل الإسم أو البريد الإلكتروني : بحيث يمكن السماح للعضو ربط الإتصال سواء باستخدام إسمه أو بريده الإلكتروني . القرار يعود لكم .
ـ حقل كلمة المرور

بعد ملأ إستمارة الدخول و إرسالها ، ليتمكن العضو من الدخول بنجاح ، يجب أن يكون قد استعمل الإسم و كلمة المرور الصحيحين أي الذين استعملهما عندما قام بفتح حسابه .
لهذا سنقوم بمقارنة الإسم و كلمة المرور الذين أرسلهما العضو . بالإسم و كلمة المرور الموجودين في قاعدة البيانات :
ـ إذا كانت البيانات صحيحة ، نقوم بفتح جلسة للعضو عبر تعيين متغيرات الجلسة
ـ أما إذا كانت خاطئة ، نشعره بوجود خطأ
ستكون لدينا صفحة "login.php" كالتالي :

login.php

<?php 
require '../includes/header.php';
require '../includes/db-connection.php';

// إذا نجح العضو في ملأ الإستمارة
if (isset($_POST['pseudo']) AND isset($_POST['pass']))
{
   // ...
   $pseudo = $_POST['pseudo'];
   $password = $_POST['pass'];
   // ...
   // أخذ البيانات من القاعدة إعتمادا على إسم العضو 
   $response= $db->prepare('SELECT user_id, user_name, user_password 
              FROM blog_users
              WHERE user_name = :nom
            ');
    $response->bindValue(':nom',$pseudo,PDO::PARAM_STR);
    $response->execute();
    $member = $response->Fetch();
    $response->CloseCursor();

   // التأكد من أن العضو موجود في قاعدة البيانات 
   if(!$member) exit('الإسم أو كلمة المرور غير صحيحين');
   // مقارنة كلمة المرور التي أرسلها العضو بالموجودة في القاعدة 
   if($password != $member['user_password']) exit('الإسم أو كلمة المرور غير صحيحين');
   // إذا كان كل شيء على ما يرام . نقوم بإنشاء متغيرات الجلسة 
   $_SESSION['id'] = $member['user_id'];
   $_SESSION['user'] = $member['user_name'];
   // ثم تحويله تلقائيا إلى أي صفحة نريد 
   header('location:../index.php');
}
?>
<form action="" method="post" id="form">
    <fieldset class="form-item">
        <legend>الدّخول</legend>
        <label for="pseudo">الإسم</label><input type="text" name="pseudo" id="pseudo"><br>
        <label for="pass">كلمة المرور</label><input type="password" name="pass" id="pass">
    </fieldset>
    <fieldset class="form-submit">
        <input type="submit" value="موافق" class="button green">
    </fieldset>
    </form>
<?php
require '../includes/footer.php';

لاستعمال متغيّرات الجلسة . مثلا لعرض إسم العضو على جميع صفحات الموقع بعد النجاح في دخوله ، يجب فقط عرض متغير الجلسة $_SESSION['user'] . مع عدم نسيان إضافة session_start في بداية الصفحات

<?php
session_start();
if(isset($_SESSION['user'])) echo htmlspecialchars($_SESSION['user']);
// ...

لعرض إسم العضو على جميع الصفحات بعد دخوله بنجاح ، و كذلك لإضافة الروابط إلى الصفحات الثلاث . أفضل مكان لتفعيل كل هذا ، هو في صفحة "header.php" . أدعوكم لفتحها لإجراء هذه التعديلات :

<?php 
session_start();
$session_id = isset($_SESSION['id']) ? (int) $_SESSION['id'] : 0;
$session_user = isset($_SESSION['user']) ? htmlspecialchars($_SESSION['user']) : '';

$message = isset($_SESSION['message']) ? htmlspecialchars($_SESSION['message']) : '';
?>
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
    <meta charset="UTF-8">
    <link href="/css/blog.css" type="text/css" rel="stylesheet">
</head>

<body>
<header id="header">
    <nav>
<?php 
if($session_id != 0)
{
    echo 'مرحبا بك : <span class="orange">'.$session_user.'</span>
    <a href="/add-blog.php" class="box">إضافة موضوع</a>
    <a href="/members/logout.php" class="box">الخروج</a>';
}
else
{
	echo '
    <a href="/members/login.php" class="box">الدخول</a>
    <a href="/members/registration.php" class="box">التسجيل</a>';
}
?>
    </nav>
    <h1>PHP <span>PDO</span><span>مدوّنتي</span></h1>
</header>
<section id="navigation">
    <div class="dropdown"><a href="#" onclick="show();">أنقر هنا لعرض و إخفاء الروابط</a></div>
    <nav id="drop">
        <a href="/">الإستقبال</a>
        <a href="">رابط 1</a>
        <a href="">رابط 2</a>
        <a href="">رابط 3</a>
        <form>
            <input type="text">
            <input type="submit" value="بحث">
        </form>
    </nav>
</section>

<section id="main">
<?php
// ... عرض رسالة أثناء قيام العضو بعملية ما : كإضافة موضوع أو تغيير بياناته الشخصية
if($message != '') echo '<div class="flush center">'.$message.'</div>';
// تدمير جلسة الإشعار مباشرة بعد عرضه
$_SESSION['message'] = '';

مثال آخر : لحماية صفحة من موقعنا ، و التي لا نسمح لرؤيتها إلا للأعضاء المتصلين .

<?php
session_start();
$session_id = (isset($_SESSION['id'])) ? (int) $_SESSION['id'] : 0;

// إذا لم يكن العضو متصلا ، نقوم بتحويله لصفحة الدخول
if($session_id == 0)
{
   header('location:members/login.php'); exit;
}

// عرض بيانات الصفحة للأعضاء المتصلين
// ...

تمرين :
قوموا بحضر الولوج إلى صفحتي التسجيل "registration.php" و الدخول "login.php" ، على الأعضاء المتصلين . لأن العضو إذا كان متصلا ليس لديه ما يفعله في الصفحتين
2 . قوموا بحماية ما تريدون على موقعكم . على كل حال ، سنعود إلى الموضوع لاحقا عندما سنحتاج إلى إنشاء المجموعات " الزوار ، الأعضاء ، المشرفون ، المدراء ..."

logout.php

صفحة الخروج و تدمير بيانات جلسة العضو .

<?php 
session_start();

$_SESSION = array();
session_destroy();
header('location:/../index.php'); exit;

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

  • التأكد من الحد الأدنى و الأقصى و مكونات النص المتاحة لكل حقل
  • التأكد من صحة البريد الإلكتروني
  • تشفير كلمة المرور قبل تخزينها في قاعدة البيانات
  • لا يجب السماح لعضوين التسجيل بنفس الإسم أو البريد الإلكتروني
  • يجب تحديد عدد المحاولات الخاطئة أثناء ربط الإتصال . مثلا إذا قام المستخدم من ملأ بيانات استمارة الدخول بشكل خاطيء ثلاث مرات على التوالي . نقوم بحضره لمدة 5 دقائق مثلا حتى يتمكن من إعادة المحاولة .

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