02‏/11‏/2014

شرح إنشاء سكربت الدخول وتسجيل عضوية بشكل آمن في PHP و MySQL

سكربت الدخول وتسجيل عضوية بشكل آمن  ,,,, المطورين يبحثون عن أفضل السبل لتأمين مواقعهم. إذا كان موقعك لديه نظام عضوا، يمكن أن يكون في خطر من التعرض للاختراق، ويمكن أن يتعرض للخطر البيانات الخاصة بالمستخدمين. هذا الدليل سوف تظهر لك محاولة واحدة على جعل دخول آمن باستخدام PHP. كود جيد كما يمكننا أن نجعل ذلك.


اولاً : تكوين قاعدة بيانات MySQL


1. إنشاء قاعدة بيانات MySQL.

تسجيل الدخول إلى قاعدة البيانات الخاصة بك كمستخدم إداري (عادة الجذر) 

في هذا الدليل سوف نقوم بإنشاء قاعدة بيانات تسمى "secure_login". 


CREATE DATABASE `secure_login`;

2. إنشاء مستخدم بامتيازات او بصلاحيات  SELECT، UPDATE و INSERT .

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

وبطبيعة الحال سوف تحتاج إلى أن تكون مسجلا في MySQL  كمستخدم لديه امتيازات كافية لإنشاء مستخدم. وعادة ما يكون هذا المستخدم الاول.

هذه هي تفاصيل المستخدم قمنا بإنشاء:

  • User: "sec_user"
  • Password: "eKcGZr59zAa2BEWU"

    تذكر ليس من الضروري أن تكون كلمة المرور معقدة بقدر الإمكان. 

    أدناه هو رمز SQL لإنشاء قاعدة بيانات للمستخدم ومنحها الأذونات الضرورية. أو يمكنك القيام بذلك في قاعدة بيانات العميل واجهة المستخدم :
    CREATE USER 'sec_user'@'localhost' IDENTIFIED BY 'eKcGZr59zAa2BEWU';
    GRANT SELECT, INSERT, UPDATE ON `secure_login`.* TO 'sec_user'@'localhost';


  • 3. انشاء جدول الاعضاء

    إنشاء الكود بالأسفل جدول مع خمسة حقول (id، واسم المستخدم والبريد الإلكتروني وكلمة المرور، salt). نستخدم نوع البيانات CHAR لحقول نعرف طول، وحقول "كلمة المرور" و "salt" لن يكون دائما 128 حرفا. باستخدام CHAR هنا يوفر على قوة المعالجة: 
    CREATE TABLE `secure_login`.`members` (
        `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
        `username` VARCHAR(30) NOT NULL,
        `email` VARCHAR(50) NOT NULL,
        `password` CHAR(128) NOT NULL,
        `salt` CHAR(128) NOT NULL 
    ) ENGINE = InnoDB;
    


    4. إنشاء جدول لتخزين محاولات تسجيل الدخول.
    سوف نستخدم هذا الجدول لتخزين محاولات تسجيل الدخول للمستخدم. هذا واحد من الطرق  التي سنجعل هجمات القوة الغاشمة أكثر صعوبة:
    CREATE TABLE `secure_login`.`login_attempts` (
        `user_id` INT(11) NOT NULL,
        `time` VARCHAR(30) NOT NULL
    ) ENGINE=InnoDB
    


    5. إنشاء صف في الجدول اختبار "أعضاء".
    سيكون من المهم أن تكون قادرة على اختبار نظام الدخول:

    • Username: test_user
    • Email: test@example.com
    • Password: 6ZaxN2Vzm9NUJT2y

      الكود يحتاج من أجل أن تكون قادرة على الدخول باسم هذا المستخدم هو:
    1. INSERT INTO `secure_login`.`members` VALUES(1, 'test_user', 'test@example.com',
      '00807432eae173f652f2064bdca1b61b290b52d40e429a7d295d76a71084aa96c0233b82f1feac45529e0726559645acaed6f3ae58a286b9f075916ebf66cacc',
      'f9aab579fc1b41ed0c44fe4ecdbfcdb4cb99b9023abb241a6db833288f4eea3c02f76e0d35204a8695077dcf81932aa59006423976224be0390395bae152d4ef');

    ثانياً : انشاء صفحة الاتصال بقاعدة البيانات 

    1. إنشاء صفحة التكوين

    إنشاء مجلد يسمى "includes" في الملف الرئيسي من التطبيق ثم قم بإنشاء ملف PHP جديد في هذا الدليل. نسميها  psl-config.php  

    تحديد الملفات تشمل خارج جذر المستند ملقم ويب يعني أن الملف لا يمكن تحديد موقع باستخدام URL. لذلك، اذا كان شخص ما أسقطت بطريق الخطأ التمديد "PHP"، مثلا، أو عابث أذونات الملف , الملف لا يزال لا يمكن عرضها كنص في نافذة المتصفح. 

    يحتوي ملف التكوين المتغيرات . أشياء مثل ما إذا كان أي شخص يمكن أن يسجل، سواء كان أو لم يكن هو اتصال آمن (HTTPS)، ويمكن أن غيرها من الاشياء فضلا عن تفاصيل قاعدة البيانات ...

    <?php
    /**
    * These are the database login details
    */
    define("HOST", "localhost"); // The host you want to connect to.
    define("USER", "sec_user"); // The database username.
    define("PASSWORD", "4Fa98xkHVd2XmnfK"); // The database password.
    define("DATABASE", "secure_login"); // The database name.
    define("CAN_REGISTER", "any");
    define("DEFAULT_ROLE", "member");
    define("SECURE", FALSE); // FOR DEVELOPMENT ONLY!!!!
    ?>


    2. انشاء صفحة الاتصال بقاعدة البيانات 

    هذا هي الشفرة PHP أننا سوف تستخدم للاتصال قاعدة بيانات MySQL لدينا. إنشاء ملف جديد يسمى 
     db_connect.php في التطبيق يشمل الدليل وإضافة الكود بالأسفل. ثم يمكنك تضمين ملف على أي صفحة كنت ترغب في الاتصال بقاعدة البيانات.
    <?php
    include_once 'psl-config.php'; // As functions.php is not included
    $mysqli = new mysqli(HOST, USER, PASSWORD, DATABASE);

    ثالثاً : انشاء دوال ال PHP 

    سوف تفعل كل هذه الوظائف معالجة نظام الدخول. إضافة كافة الوظائف إلى صفحة تسمى functions.php في الدليل يتضمن التطبيق.
    1. بدء جلسة بشكل آمن PHP.
    ومن المعروف جلسات PHP لا تكون آمنة، وبالتالي فإنه من المهم ليس فقط لوضع "session_start ()؛" في أعلى كل صفحة التي تريد استخدامها جلسات PHP. نحن بصدد إنشاء دالة يسمى "sec_session_start ()"، وهذا سوف بدء جلسة PHP بطريقة آمنة. يجب استدعاء هذه الدالة في الجزء العلوي من أي صفحة التي ترغب في الوصول إلى متغير جلسة PHP. إذا كنت قلقا حقا حول الأمن والخصوصية لملفات تعريف الارتباط الخاصة بك، يكون النظر في هذه المقالة:

    إنشاء ملف جديد يسمى functions.php في التطبيق الخاص بك يتضمن الدليل وإضافة التعليمة البرمجية التالية إليه:

    1. <?php
      include_once 'psl-config.php';
      function sec_session_start() {
      $session_name = 'sec_session_id'; // Set a custom session name
      $secure = SECURE;
      // This stops JavaScript being able to access the session id.
      $httponly = true;
      // Forces sessions to only use cookies.
      if (ini_set('session.use_only_cookies', 1) === FALSE) {
      header("Location: ../error.php?err=Could not initiate a safe session (ini_set)");
      exit();
      }
      // Gets current cookies params.
      $cookieParams = session_get_cookie_params();
      session_set_cookie_params($cookieParams["lifetime"],
      $cookieParams["path"],
      $cookieParams["domain"],
      $secure,
      $httponly);
      // Sets the session name to the one set above.
      session_name($session_name);
      session_start(); // Start the PHP session
      session_regenerate_id(); // regenerated the session, delete the old one.
      }
    2. انشاء دالة الدخول .
    وتتضمن المهمة التحقق من البريد الإلكتروني وكلمة المرور من قاعدة البيانات. فإنه سيعود صحيح إذا كان هناك تطابق. إضافة هذه الدالة إلى ملف functions.php الخاص بك:
    function login($email, $password, $mysqli) {
    // Using prepared statements means that SQL injection is not possible.
    if ($stmt = $mysqli->prepare("SELECT id, username, password, salt
    FROM members
    LIMIT 1")) {
    WHERE email = ?
    $stmt->bind_param('s', $email); // Bind "$email" to parameter.
    $stmt->execute(); // Execute the prepared query.
    $stmt->store_result();
    // get variables from result.
    $stmt->bind_result($user_id, $username, $db_password, $salt);
    $stmt->fetch();
    // hash the password with the unique salt.
    $password = hash('sha512', $password . $salt);
    if ($stmt->num_rows == 1) {
    // If the user exists we check if the account is locked
    // from too many login attempts
    if (checkbrute($user_id, $mysqli) == true) {
    // Account is locked
    // Send an email to user saying their account is locked
    return false;
    } else {
    // Check if the password in the database matches
    // the password the user submitted.
    if ($db_password == $password) {
    // Password is correct!
    // Get the user-agent string of the user.
    $user_browser = $_SERVER['HTTP_USER_AGENT'];
    // XSS protection as we might print this value
    $user_id = preg_replace("/[^0-9]+/", "", $user_id);
    $_SESSION['user_id'] = $user_id;
    // XSS protection as we might print this value
    $username = preg_replace("/[^a-zA-Z0-9_\-]+/",
    "",
    $username);
    $_SESSION['username'] = $username;
    $_SESSION['login_string'] = hash('sha512',
    $password . $user_browser);
    // Login successful.
    return true;
    } else {
    // Password is not correct
    // We record this attempt in the database
    $now = time();
    $mysqli->query("INSERT INTO login_attempts(user_id, time)
    VALUES ('$user_id', '$now')");
    return false;
    }
    }
    } else {
    // No user exists.
    return false;
    }
    }
    }

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

    هجمات القوة الغاشمة من الصعب منع. وهناك عدد قليل من الطرق يمكننا منعهم تستخدم اختبار CAPTCHA، قفل حسابات المستخدمين وإضافة تأخير في تسجيل الدخول الفاشلة، لذلك لا يمكن للمستخدم الدخول لآخر ثلاثين ثانية.

    ونحن نوصي بشدة باستخدام CAPTCHA. حتى الآن نحن لم تنفذ هذه الداله في رمز المثال، ولكن نأمل أن تفعل ذلك في المستقبل القريب، وذلك باستخدام SecureImage، نظرا لأنه لا يتطلب التسجيل. قد تفضل شيئا المعروفة مثل اختبار reCAPTCHA من Google.

    أيهما النظام الذي تقرر، نقترح عليك فقط عرض صورة CAPTCHA بعد اثنين محاولات فاشلة لتسجيل الدخول وذلك لتجنب الازعاج للمستخدم دون داع.
    في التعليمات البرمجية لدينا سنقوم بتسجيل المحاولات الفاشلة وقفل حساب المستخدم بعد خمس محاولات فاشلة لتسجيل الدخول. وهذا ينبغي أن يؤدي إرسال بريد إلكتروني إلى المستخدم مع وصلة إعادة تعيين كلمة السر، لكننا لم تنفذ هذا في التعليمات البرمجية الخاصة بنا. هنا هي الشفرة للcheckbrute وظيفة () في وقت كتابة المقال. إضافته إلى الملف functions.php الخاص بك:


    function checkbrute($user_id, $mysqli) {
    // Get timestamp of current time
    $now = time();
    // All login attempts are counted from the past 2 hours.
    $valid_attempts = $now - (2 * 60 * 60);
    if ($stmt = $mysqli->prepare("SELECT time
    FROM login_attempts
    WHERE user_id = ?
    AND time > '$valid_attempts'")) {
    $stmt->bind_param('i', $user_id);
    // Execute the prepared query.
    $stmt->execute();
    $stmt->store_result();
    // If there have been more than 5 failed logins
    if ($stmt->num_rows > 5) {
    return true;
    } else {
    return false;
    }
    }
    }


    4. تحقق المسجلين في المركز.
    ونحن نفعل ذلك عن طريق التحقق من "USER_ID" و "login_string" متغيرات الدورة. المتغير "login_string" الدورة ديه معلومات متصفح المستخدم تجزئته مع كلمة المرور. نحن نستخدم المعلومات المتصفح لأنه من المستبعد جدا أن المستخدم لن يتغير متصفح منتصف الجلسة الخاصة بهم. القيام بذلك يساعد على منع اختطاف الجلسة إضافة هذه الدالة إلى ملف functions.php الخاص بك في مجلد يتضمن التطبيق الخاص بك:
    function login_check($mysqli) {
    // Check if all session variables are set
    if (isset($_SESSION['user_id'],
    $_SESSION['username'],
    $_SESSION['login_string'])) {
    $user_id = $_SESSION['user_id'];
    $login_string = $_SESSION['login_string'];
    $username = $_SESSION['username'];
    // Get the user-agent string of the user.
    $user_browser = $_SERVER['HTTP_USER_AGENT'];
    if ($stmt = $mysqli->prepare("SELECT password
    FROM members
    WHERE id = ? LIMIT 1")) {
    // Bind "$user_id" to parameter.
    $stmt->bind_param('i', $user_id);
    $stmt->execute(); // Execute the prepared query.
    $stmt->store_result();
    if ($stmt->num_rows == 1) {
    // If the user exists get variables from result.
    $stmt->bind_result($password);
    $stmt->fetch();
    $login_check = hash('sha512', $password . $user_browser);
    if ($login_check == $login_string) {
    // Logged In!!!!
    return true;
    } else {
    // Not logged in
    return false;
    }
    } else {
    // Not logged in
    return false;
    }
    } else {
    // Not logged in
    return false;
    }
    } else {
    // Not logged in
    return false;
    }
    }

    5. تعقيم URL من PHP_SELF

    هذه الدالة القادمة يعقم الإخراج من متغير الخادم PHP_SELF. وهو modificaton :

    function esc_url($url) {
    if ('' == $url) {
    return $url;
    }
    $url = preg_replace('|[^a-z0-9-~+_.?#=!&;,/:%@$\|*\'()\\x80-\\xff]|i', '', $url);
    $strip = array('%0d', '%0a', '%0D', '%0A');
    $url = (string) $url;
    $count = 1;
    while ($count) {
    $url = str_replace($strip, '', $url, $count);
    }
    $url = str_replace(';//', '://', $url);
    $url = htmlentities($url);
    $url = str_replace('&amp;', '&#038;', $url);
    $url = str_replace("'", '&#039;', $url);
    if ($url[0] !== '/') {
    // We're only interested in relative links from $_SERVER['PHP_SELF']
    return '';
    } else {
    return $url;
    }
    }


    رابعاً : إنشاء صفحات المعالجة :

    1. إنشاء صفحة معالجة الدخول (process_login.php)

    إنشاء ملف لعملية تسجيل الدخول، ويسمى في process_login.php و حفظ في ملف "includes ". وغني في هذا الملف لأنه يحتوي على أي العلامات HTML.
    سوف نستخدم mysqli_ * مجموعة من دوالPHP لأن هذا هو واحد من أكثر ملحقات mySQL يصل إلى التاريخ.
    <?php
    include_once 'db_connect.php';
    include_once 'functions.php';
    sec_session_start(); // Our custom secure way of starting a PHP session.
    if (isset($_POST['email'], $_POST['p'])) {
    $email = $_POST['email'];
    $password = $_POST['p']; // The hashed password.
    if (login($email, $password, $mysqli) == true) {
    // Login success
    header('Location: ../protected_page.php');
    } else {
    // Login failed
    header('Location: ../index.php?error=1');
    }
    } else {
    // The correct POST variables were not sent to this page.
    echo 'Invalid Request';
    }

    2. إنشاء سكربت الخروج.

    إدخال الرمز الحالي لتسجيل الخروج للمستخدم، والتي يجب أن تضاف إلى ملف يسمى logout.php في ملف التطبيق includes  هو:

    <?php
    include_once 'functions.php';
    sec_session_start();
     
    // Unset all session values 
    $_SESSION = array();
     
    // get session parameters 
    $params = session_get_cookie_params();
     
    // Delete the actual cookie. 
    setcookie(session_name(),
            '', time() - 42000, 
            $params["path"], 
            $params["domain"], 
            $params["secure"], 
            $params["httponly"]);
     
    // Destroy session 
    session_destroy();
    header('Location: ../index.php');

    3. صفحة التسجيل Registration .
    يتم تضمين رمز التسجيل في ملفين جديدة يسمى register.php في الملف الرئيسي الخاص بالتطبيق ويشمل register.inc.php في الملف. وهو يفعل الأشياء التالية:

    ويحصل بالتحقق من صحة اسم المستخدم  
    ويحصل يؤكد عنوان البريد الإلكتروني للمستخدم 
    ويحصل بالتحقق من صحة كلمة السر للمستخدم 

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

    الآن، فقط إنشاء ملف register.php وتشمل التعليمات البرمجية التالية فيه:

    <?php
    include_once 'includes/register.inc.php';
    include_once 'includes/functions.php';
    ?>
    <!DOCTYPE html>
    <html>
            <meta charset="UTF-8">
    <head>
            <title>Secure Login: Registration Form</title>
            <script type="text/JavaScript" src="js/sha512.js"></script> 
    <script type="text/JavaScript" src="js/forms.js"></script>
        <body>
    <link rel="stylesheet" href="styles/main.css" /> </head>
            set or if the registration script caused an error. -->
    <!-- Registration form to be output if the POST variables are not <h1>Register with us</h1>
            <?php
            if (!empty($error_msg)) {
                echo $error_msg;
            }
            ?>
            <ul>
                <li>Usernames may contain only digits, upper and lower case letters and underscores</li>
    <li>Emails must have a valid email format</li>
                <li>Passwords must contain
    <li>Passwords must be at least 6 characters long</li> <ul>
                        <li>At least one lower case letter (a..z)</li>
    <li>At least one upper case letter (A..Z)</li> <li>At least one number (0..9)</li> </ul>
            <form action="<?php echo esc_url($_SERVER['PHP_SELF']); ?>" 
    </li> <li>Your password and confirmation must match exactly</li> </ul>
    method="post"
                    name="registration_form">
    Username: <input type='text'
                Email: <input type="text" name="email" id="email" /><br>
    name='username' id='username' /><br>
                                 name="password" 
    Password: <input type="password" id="password"/><br>
                                         id="confirmpwd" /><br>
    Confirm password: <input type="password" name="confirmpwd" <input type="button"
                                       this.form.username,
    value="Register" onclick="return regformhash(this.form, this.form.email,
            <p>Return to the <a href="index.php">login page</a>.</p>
    this.form.password, this.form.confirmpwd);" /> </form> </body>
    </html>

    على الملف register.inc.php في الملف includes  ينبغي أن تتضمن التعليمات البرمجية التالية:

    <?php
    include_once 'db_connect.php';
    include_once 'psl-config.php';
     
    $error_msg = "";
     
    if (isset($_POST['username'], $_POST['email'], $_POST['p'])) {
        // Sanitize and validate the data passed in
        $username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);
        $email = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL);
        $email = filter_var($email, FILTER_VALIDATE_EMAIL);
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            // Not a valid email
            $error_msg .= '<p class="error">The email address you entered is not valid</p>';
        }
     
        $password = filter_input(INPUT_POST, 'p', FILTER_SANITIZE_STRING);
        if (strlen($password) != 128) {
            // The hashed pwd should be 128 characters long.
            // If it's not, something really odd has happened
            $error_msg .= '<p class="error">Invalid password configuration.</p>';
        }
     
        // Username validity and password validity have been checked client side.
        // This should should be adequate as nobody gains any advantage from
        // breaking these rules.
        //
     
        $prep_stmt = "SELECT id FROM members WHERE email = ? LIMIT 1";
        $stmt = $mysqli->prepare($prep_stmt);
     
       // check existing email  
        if ($stmt) {
            $stmt->bind_param('s', $email);
            $stmt->execute();
            $stmt->store_result();
     
            if ($stmt->num_rows == 1) {
                // A user with this email address already exists
                $error_msg .= '<p class="error">A user with this email address already exists.</p>';
                            $stmt->close();
            }
                    $stmt->close();
        } else {
            $error_msg .= '<p class="error">Database error Line 39</p>';
                    $stmt->close();
        }
     
        // check existing username
        $prep_stmt = "SELECT id FROM members WHERE username = ? LIMIT 1";
        $stmt = $mysqli->prepare($prep_stmt);
     
        if ($stmt) {
            $stmt->bind_param('s', $username);
            $stmt->execute();
            $stmt->store_result();
     
                    if ($stmt->num_rows == 1) {
                            // A user with this username already exists
                            $error_msg .= '<p class="error">A user with this username already exists</p>';
                            $stmt->close();
                    }
                    $stmt->close();
            } else {
                    $error_msg .= '<p class="error">Database error line 55</p>';
                    $stmt->close();
            }
     
        // TODO: 
        // We'll also have to account for the situation where the user doesn't have
        // rights to do registration, by checking what type of user is attempting to
        // perform the operation.
     
        if (empty($error_msg)) {
            // Create a random salt
            //$random_salt = hash('sha512', uniqid(openssl_random_pseudo_bytes(16), TRUE)); // Did not work
            $random_salt = hash('sha512', uniqid(mt_rand(1, mt_getrandmax()), true));
     
            // Create salted password 
            $password = hash('sha512', $password . $random_salt);
     
            // Insert the new user into the database 
            if ($insert_stmt = $mysqli->prepare("INSERT INTO members (username, email, password, salt) VALUES (?, ?, ?, ?)")) {
                $insert_stmt->bind_param('ssss', $username, $email, $password, $random_salt);
                // Execute the prepared query.
                if (! $insert_stmt->execute()) {
                    header('Location: ../error.php?err=Registration failure: INSERT');
                }
            }
            header('Location: ./register_success.php');
        }
    }
    


    خامساً : إنشاء ملفات جافا سكريبت :

    1. 
    إنشاء ملف sha512.js 

    هذا الملف هو تنفيذ في جافا سكريبت لSHA512 خوارزمية التجزئة. سوف نستخدم وظيفة التجزئة حتى كلمات المرور لدينا لا تحصل على إرسالها في نص عادي. 

    على الملف يمكن تحميله من pajhome.org.uk 


    تخزين نسخة من هذا الملف في الملف يسمى "JS"، قبالة الملف الرئيسي للتطبيق.

    2. 
    إنشاء ملف forms.js 
    هذا الملف، الذي يجب إنشاء في الملف JS من التطبيق، سوف يعالج تجزئة كلمات المرور لتسجيل الدخول (formhash ()) والتسجيل (regformhash ()) forms:

    function formhash(form, password) {
        // Create a new element input, this will be our hashed password field. 
        var p = document.createElement("input");
     
        // Add the new element to our form. 
        form.appendChild(p);
        p.name = "p";
        p.type = "hidden";
        p.value = hex_sha512(password.value);
     
        // Make sure the plaintext password doesn't get sent. 
        password.value = "";
     
        // Finally submit the form. 
        form.submit();
    }
     
    function regformhash(form, uid, email, password, conf) {
         // Check each field has a value
        if (uid.value == ''         || 
              email.value == ''     || 
              password.value == ''  || 
              conf.value == '') {
     
            alert('You must provide all the requested details. Please try again');
            return false;
        }
     
        // Check the username
     
        re = /^\w+$/; 
        if(!re.test(form.username.value)) { 
            alert("Username must contain only letters, numbers and underscores. Please try again"); 
            form.username.focus();
            return false; 
        }
     
        // Check that the password is sufficiently long (min 6 chars)
        // The check is duplicated below, but this is included to give more
        // specific guidance to the user
        if (password.value.length < 6) {
            alert('Passwords must be at least 6 characters long.  Please try again');
            form.password.focus();
            return false;
        }
     
        // At least one number, one lowercase and one uppercase letter 
        // At least six characters 
     
        var re = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,}/; 
        if (!re.test(password.value)) {
            alert('Passwords must contain at least one number, one lowercase and one uppercase letter.  Please try again');
            return false;
        }
     
        // Check password and confirmation are the same
        if (password.value != conf.value) {
            alert('Your password and confirmation do not match. Please try again');
            form.password.focus();
            return false;
        }
     
        // Create a new element input, this will be our hashed password field. 
        var p = document.createElement("input");
     
        // Add the new element to our form. 
        form.appendChild(p);
        p.name = "p";
        p.type = "hidden";
        p.value = hex_sha512(password.value);
     
        // Make sure the plaintext password doesn't get sent. 
        password.value = "";
        conf.value = "";
     
        // Finally submit the form. 
        form.submit();
        return true;
    }
    

    في الحالتينفإنجافا سكريبت تجزئات كلمة المرور ويمر في البانات من خلال إنشاء وملء حقل مخفي.


    سادساً : 
    إنشاء صفحات HTML:

    1. إنشاء نموذج الدخول (login.php).

    هذا هو شكل HTML مع
    اثنين من 
    حقول النصية ، واسمه "البريد الإلكتروني" و "كلمة المرور". يدعو زر تقديم النموذج دالة جافا سكريبت formhash ()، والتي سوف تولد تجزئة من كلمة المرور، وإرسال "البريد الإلكتروني" و (كلمة المرور تجزئته) إلى الملقم. يجب إنشاء هذا الملف في الملف الرئيسي الخاص بالتطبيق.

    <?php
    include_once 'includes/db_connect.php';
    include_once 'includes/functions.php';
     
    sec_session_start();
     
    if (login_check($mysqli) == true) {
        $logged = 'in';
    } else {
        $logged = 'out';
    }
    ?>
    <!DOCTYPE html>
    <html>
        <head>
            <title>Secure Login: Log In</title>
            <link rel="stylesheet" href="styles/main.css" />
            <script type="text/JavaScript" src="js/sha512.js"></script> 
            <script type="text/JavaScript" src="js/forms.js"></script> 
        </head>
        <body>
            <?php
            if (isset($_GET['error'])) {
                echo '<p class="error">Error Logging In!</p>';
            }
            ?> 
            <form action="includes/process_login.php" method="post" name="login_form">                      
                Email: <input type="text" name="email" />
                Password: <input type="password" 
                                 name="password" 
                                 id="password"/>
                <input type="button" 
                       value="Login" 
                       onclick="formhash(this.form, this.form.password);" /> 
            </form>
            <p>If you don't have a login, please <a href="register.php">register</a></p>
            <p>If you are done, please <a href="includes/logout.php">log out</a>.</p>
            <p>You are currently logged <?php echo $logged ?>.</p>
        </body>
    </html>
    


    2. إنشاء صفحة register_success.php 

    إنشاء صفحة ويب جديدة تسمى PHP register_success.php، في الملف الجذر للتطبيق. هذه هي الصفحة التي يتم إعادة توجيه المستخدم بعد التسجيل بنجاح. بالطبع يمكنك جعل هذه الصفحة أي شيء تريد أو إعادة توجيه إلى صفحة أخرى تماما , والامر متروك لك. الصفحة يجب أن يكون موجودا في الملف الرئيسي للتطبيق. الصفحة register_success.php الحالية التي كتبناه تبدو مثل هذا:


    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title>Secure Login: Registration Success</title>
            <link rel="stylesheet" href="styles/main.css" />
        </head>
        <body>
            <h1>Registration successful!</h1>
            <p>You can now go back to the <a href="index.php">login page</a> and log in</p>
        </body>
    </html>
    


    3. إنشاء صفحة الخطأ

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

    <?php
    $error = filter_input(INPUT_GET, 'err', $filter = FILTER_SANITIZE_STRING);
     
    if (! $error) {
        $error = 'Oops! An unknown error happened.';
    }
    ?>
    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title>Secure Login: Error</title>
            <link rel="stylesheet" href="styles/main.css" />
        </head>
        <body>
            <h1>There was a problem</h1>
            <p class="error"><?php echo $error; ?></p>  
        </body>
    </html>
    


    سابعاً : حماية الصفحات:

    1. لحماية سكريبت.

    واحدة من المشاكل الأكثر شيوعا مع أنظمة التوثيق هي المطور ننسى للتحقق مما إذا تم تسجيل المستخدم في. ومن المهم جدا استخدام الكود بالأسفل في كل صفحة محمية للتأكد من أن يتم تسجيل المستخدم . تأكد من استخدام هذه الدالة للتحقق مما إذا تم تسجيل المستخدم .
    // Include database connection and functions here.  See 3.1. 
    sec_session_start(); 
    if(login_check($mysqli) == true) {
            // Add your protected page content here!
    } else { 
            echo 'You are not authorized to access this page, please login.';
    }
    


    كمثال على ما يجب القيام به، أدرجنا صفحة عينة المحمية. إنشاء ملف يسمى protected_page.php في الملف الرئيسي  للتطبيق. يجب أن يحتوي الملف على شيء كما يلي:
    <?php
    include_once 'includes/db_connect.php';
    include_once 'includes/functions.php';
     
    sec_session_start();
    ?>
    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title>Secure Login: Protected Page</title>
            <link rel="stylesheet" href="styles/main.css" />
        </head>
        <body>
            <?php if (login_check($mysqli) == true) : ?>
                <p>Welcome <?php echo htmlentities($_SESSION['username']); ?>!</p>
                <p>
                    This is an example protected page.  To access this page, users
                    must be logged in.  At some stage, we'll also check the role of
                    the user, so pages will be able to determine the type of user
                    authorised to access the page.
                </p>
                <p>Return to <a href="index.php">login page</a></p>
            <?php else : ?>
                <p>
                    <span class="error">You are not authorized to access this page.</span> Please <a href="index.php">login</a>.
                </p>
            <?php endif; ?>
        </body>
    </html>
    



    2 التعليقات :

    1. السلام عليكم ورحمة الله في البداية أشكر لك على هذا الموضوع وعلى الدخول بالتفاصيل لكنني واجهت بعض المشاكل ولم استطيع حلها من ضمن هذا المشاكل
      أنني لم استطيع الدخول بالاسم الذي انت كتبته ودائما تظهر لي رسالة THERE WAS A PROBLEM في جميع الحالات تظهر لي هذه الرسالة
      أرجو ان تتكرم علي بتوضيح سبب المشكلة بالرغم انني قمت بعمل جميع الخطوات وشكرا لك

      ردحذف