سه شنبه ۰۱ تیر ۱۴۰۰

Tuesday, June 22, 2021 GMT +4:30

» هوشمند سازی پنل ورود و خروج سایت با PHP و MySQL

mysql-php-smart-login

در مطالب قبل از بخش آموزش کاربردی کار با PHP و MySQL برای طراحی امکانات مختلف مورد نیاز برنامه های تحت وب به طور مفصل به مبحث ساخت فرم عضویت و نحوه ورود و خروج کاربران به پنل مدیریت سایت پرداختیم، بحث نشست ها (سشن یا Session) را با هم مرور کرده و با نحوه رمزنگاری و تطبیق کلمه عبور و همچنین ذخیره و بازیابی اطلاعات اعضاء سایت آشنا شدیم، این بار در تکمیل آموزش های قبل می خواهیم کمی بیشتر بخش مدیریت سایتمان را توسعه داده و آن را به اصطلاح هوشمندتر کنیم، در این یادداشت به همراه نمونه کدهایی خواهیم دید که چگونه می توانیم امکاناتی مانند "مرا به خاطر بسپار" و "خروج خودکار کاربر بعد از چند دقیقه غیر فعال بودن" را به سیستم مدیریت سایتمان اضافه کنیم.

نکته مهم: معمولا قابلیت "مرا به خاطر بسپار" برای برنامه هایی که به امنیت بالایی احتیاج دارند توصیه نمی شود، اگر کاربر به هر دلیل از برنامه به شکل استاندارد خارج نشود (به فرض پنجره مرورگر خود را ببندد یا جریان برق به طور ناگهانی قطع شود) با توجه به وجود کوکی یادآوری در حافظه، اشخاص دیگر بر روی همان سیستم و همان مرورگر می توانند بدون وارد کردن نام کاربری و کلمه عبور و تنها با داشتن آدرس URL صفحه کاربری به پنل مدیریت برنامه دسترسی پیدا کنند! متاسفانه این مشکلی است که بیشتر از روی عدم آگاهی کاربران و معمولا در کامپیوترهای اشتراکی مورد استفاده در اماکن عمومی مانند کافی نت ها، مراکز دانشگاهی و... اتفاق می افتد، لذا در نظر گرفتن این امکان باید با نمایش هشدارهای لازم و رعایت نکات امنیتی باشد.

ایجاد امکان "مرا به خاطر بسپار" در پنل مدیریت سایت


سایت های زیادی را دیده ایم که در قسمت ورود اطلاعات نام کاربری و کلمه عبور معمولا با دکمه ای به صورت چک باکس امکانی تحت عنوان "مرا به خاطر بسپار" یا با عبارات مشابه ارائه می کنند، این امکان در واقع بدین معنی است که سیستم تا مدت زمان معینی در مراجعات بعدی از کاربر نام کاربری و کلمه عبور درخواست نکرده و به صورت هوشمندانه وضعیت ورود او را به یاد خواهد داشت، اما امکان "مرا به خاطر بسپار" چگونه در پنل مدیریت ایجاد می شود؟
اگر به صورت اجمالی بخواهیم ساز و کار این امکان را بررسی کنیم به این صورت خواهد بود:
هنگامی که گزینه یادآوری را انتخاب و فرم را ارسال می کنیم برنامه با دستورات PHP (یا JavaScript) یک کوکی (Cookie) با تاریخ انقضای مد نظرمان در مرورگر ایجاد کرده و با مقداری مشابه در سرور فایل سشن را نیز ذخیره می کند، مقدار کوکی - سشن معمولا عبارت متنی 22 تا 40 کاراکتری اتفاقی شامل حروف و اعداد انگلیسی است که با توابع رمزنگاری (در حال حاضر MD5 و SHA-1) ایجاد می شود، اطلاعات سشن به صورت پیش فرض برای مدت زمانی کوتاه (معمولا 1440 ثانیه معادل 24 دقیقه) نگهداری و سپس حذف خواهد شد، لذا به عنوان برنامه نویس برای اینکه مدت زمان مد نظر بیشتری اعمال کنیم (به فرض یک ماه) دو راه حل در اختیار داریم:
- ایجاد تغییرات در تنظیمات فایل php.ini حین اجرا و افزایش مدت زمان پیش فرض نگهداری سشن ها (این روش توصیه نمی شود).
- نگهداری مقدار سشن آی دی در دیتابیس و در صورت نیاز آپدیت مدت زمان اعتبار یا تنظیم مجدد کوکی و سشن (در صورت انقضاء).

تغییر تنظیمات فایل php.ini حین اجرا


برای حالت اول یعنی ایجاد تغییرات در تنظیمات فایل php.ini (حاوی تنظیمات پیش فرض مفسر PHP) معمولا نیازی به ویرایش دستی این فایل نیست، در صورت پشتیبانی سرور کافی است دستورات زیر را در ابتدای هر صفحه که نشست در آن فعال است قرار دهیم تا در حین اجرای کدها، تنظیمات پیش فرض لغو و با مقادیر مد نظرمان جایگزین شوند:
<?php
//یک ساعت به ثانیه * ساعات یک روز * تعداد روزهای یک ماه = یک ماه به ثانیه
ini_set('session.gc_maxlifetime', 3600 * 24 * 30);
ini_set('session.cookie_lifetime', 3600 * 24 * 30);
ini_set('session.cache_expire', 3600 * 24 * 30);
session_name('panel');
session_start();
?>
کسب اطلاعات بیشتر در خصوص فایل php.ini:
https://www.php.net/manual/en/function.ini-set.php
اگرچه این روش به اصلاح دم دستی و سریع است اما ممکن است همیشه نتیجه مطلوب ندهد و لذا خیلی قابل اتکا نیست، روش بهتر استفاده از دیتابیس جهت نگهداری اطلاعات کوکی - سشن آی دی و به روزرسانی یا تنظیم مجدد سشن است که در ادامه بررسی خواهیم کرد.

نگهداری مقدار سشن آی دی در دیتابیس و آپدیت یا تنظیم مجدد کوکی و سشن


در شیوه دوم و استفاده از دیتابیس تا زمانی که کوکی مورد نظر در مرورگر وجود دارد و به دلیل منقضی شدن تاریخ کوکی یا کلیک کاربر بر روی دکمه خروج Unset و حذف نشده است، مرورگر در هر درخواست مقدار کوکی را به سرور ارسال کرده و در نتیجه وضعیت دسترسی کاربر برای برنامه قابل شناسایی است و بدون ورود نام کاربری و کلمه عبور حتی با بستن پنجره مرورگر و مراجعه بعدی می تواند از امکانات بخش اعضاء سایت استفاده کند، اما قاعدتا انجام این موارد توسط برنامه نیاز به نوشتن دستورات و ایجاد تغییراتی در ساختار و کدهای پنل مدیریت سایت دارد که در ادامه خواهیم دید.
نکته: برای مشاهده اطلاعات و سربرگ هایی که بین واسط کاربری و سرور رد و بدل می شود می توانیم در مرورگرهای جدید با فشردن دکمه F12 از قسمت Console و Network استفاده کنیم.

ایجاد فولدری با نام php-mysql-signin-smart


برای تجمیع و مدیریت ساده تر فایل های سیستم هوشمند پنل ورود و خروج سایت بهتر است یک دایرکتوری مجزا در نظر بگیریم، در این آموزش ساز و کاری که در آموزش قبل در خصوص ایجاد پنل ورود و خروج سایت گفتیم را توسعه می دهیم با این حال برای جلوگیری از سردرگمی فولدری جداگانه با نام دلخواه php-mysql-signin-smart ساخته ایم که در مجموع چند فایل و فولدر زیر را شامل می شود:
- فایل config.php، حاوی اطاعات اتصال به دیتابیس.
- فایل create.php، جهت ایجاد جدول و ستون ها.
- فایل index.php، فرم HTML ورود به پنل مدیریت و ترکیب آن با دستورات PHP.
- فایل login.php، بررسی معتبر بودن اطلاعات ارسالی کاربران و انتقال به پنل مدیریت.
- فایل panel.php، پنل مدیریت کاربران سایت.
- فایل script.js، محاسبه و نمایش مدت زمان باقیمانده از نشست در سمت کاربر.
فایل access.php، بررسی وضعیت دسترسی کاربر و اعتبار نشست.
- فایل logout.php، انقضای کامل نشست و خروج از پنل مدیریت.
- فولدر lib، شامل فایلی با نام password_compat.php جهت استفاده از قابلیت های توابع جدید کلمه عبور در نسخه 5.5 و قدیمی تر PHP.
در ادامه با جزئیات این فایل ها را بررسی می کنیم.

تنظیم اطلاعات اتصال به دیتابیس در فایل config.php


طبق روال برای اتصال به دیتابیس نیاز به تنظیم چند پارامتر در تابع mysqli_connect است که شامل نام سرور، نام کاربری دیتابیس، کلمه عبور دیتابیس و در نهایت عنوان دیتابیس است، برای تجمیع این موارد و استفاده چندباره از تنظیمات پیکربندی در صفحات مختلف معمولا از فایل Configuration استفاده می شود که در این آموزش نیز بر همین اساس اطلاعات را در فایلی با نام دلخواه config.php به صورت نمونه زیر قرار داده ایم:
<?php
//تنظیمات اتصال به دیتابیس
$config = array(
    'host' => 'localhost',
    'db_user' => 'نام کاربری دیتابیس',
    'db_pass' => 'کلمه عبور دیتابیس',
    'db_name' => 'نام دیتابیس'
);
?>
این فایل جهت نمونه است و باید مطابق با اطلاعات دیتابیسی که در آموزش های قبل ساخته ایم تکمیل شود، در صورتی که این آموزش ها را مطالعه نکرده اید لطفا ابتدا از بخش آموزش های کاربردی سایت مطالب مرتبط به مبحث ثبت نام و عضویت کاربران و همچنین ورود به پنل مدیریت را مطالعه کنید (برای دسترسی سریعتر می توانید از دکمه "قبلی" در انتهای همین صفحه نیز استفاده کنید).

ساخت جدول sessions جهت نگهداری اطلاعات نشست در دیتابیس


برای ایجاد امکان هوشمندسازی پنل مدیریت سایت در کنار جدول users که در دو آموزش قبلی ساخته ایم نیاز به ایجاد جدول دیگری تحت عنوان sessions است که اطلاعات نشست هر کاربر را در ستون هایی نگهداری کند، گفتیم که نشست ها در PHP به صورت پیش فرض تنها 24 دقیقه معتبر هستند و در صورتی که طی این مدت کاربر صفحه ای را فراخوانی نکند خود به خود منقضی شده و کاربر باید مجددا وارد پنل شود، لذا برای نگهداری طولانی مدت اطلاعات نشست و ایجاد امکان "مرا بخاطر بسپار" گزینه متداول استفاده از ساز و کار دیتابیس است، بدین منظور کدهای زیر را در فایل create.php قرار داده و این فایل را در مرورگر خود (لوکال یا آنلاین) فراخوانی می کنیم:
<?php
//فایل تنظیمات اتصال به دیتابیس
include_once('config.php');

//اتصال به دیتابیس
$conn = mysqli_connect($config['host'], $config['db_user'], $config['db_pass'], $config['db_name']);

if(!$conn) {
    echo "PHP & MySQL Connection: Error! " . mysqli_connect_errno() . ' - ' . mysqli_connect_error();
    exit;
} else {
    echo "PHP & MySQL Connection: Ok!<br>";

    //نام جدول
    $tbl_name = "sessions";

    //ساخت جدول و ستون ها
    $sql = "CREATE TABLE $tbl_name(
    id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(255),
    remember TINYINT(1) NOT NULL DEFAULT 0,
    session_value VARCHAR(255),
    session_date DATETIME)
    ENGINE=MyISAM DEFAULT CHARACTER SET=utf8 COLLATE=utf8_persian_ci"
;
    $query = mysqli_query($conn, $sql);

    if(!$query) {
        echo "Creating Table $tbl_name: Error! " . mysqli_error($conn) . "<br>";
    } else {
        echo "Creating Table $tbl_name: OK!<br>";
    }

    //افزودن ستون ها به ایندکس جهت افزایش سرعت پرس و جوها
    if(!$query) {
        $sql = "ALTER TABLE $tbl_name ADD INDEX `username` (`username`)";
        $query = mysqli_query($conn, $sql);
    }

    if(!$query) {
        $sql = "ALTER TABLE $tbl_name ADD INDEX `session_value` (`session_value`)";
        $query = mysqli_query($conn, $sql);
    }

    if(!$query) {
        echo "Altering Table $tbl_name: Error! " . mysqli_error($conn);
    } else {
        echo "Altering Table $tbl_name: OK!";
    }
}

//پایان اتصال
mysqli_close($conn);
?>
توضیح:
- ستون id را به صورت UNSIGNED در نظر گرفته ایم، این پارامتر یعنی ستون id صرفا شامل اعداد مثبت خواهد بود و به این صورت حداکثر ظرفیت اسمی آن از عدد 2147483647 به 4294967295 افزایش خواهد یافت:
https://dev.mysql.com/doc/refman/5.6/en/integer-types.html
- جدول sessions شامل پنج ستون id, username, remember, session_value و session_date است که هر ستون را با هدف خاصی در نظر گرفته ایم.
- ستون id شماره ردیف یکتا، ستون username نام کاربر، ستون remember وضعیت یادآوری، ستون session_value مقادیر کوکی - سشن آی دی و در نهایت ستون session_date تاریخ انقضای نشست را در خود جای می دهند.
نکته: این جدول در یک دیتابیس و کنار جدول users که در آموزش های گذشته برای ثبت نام و عضویت کاربر استفاده شده باید ایجاد گردد.

افزودن چک باکس یادآوری به فرم HTML ورود


برای ایجاد امکان "مرا بخاطر بسپار" به فرم HTML که در آموزش قبل جهت ورود به پنل مدیریت سایت ساخته ایم یک فیلد input از نوع چک باکس (checkbox) اضافه می کنیم، در صورتی که این آموزش را مطالعه نکرده اید لطفا ابتدا از بخش آموزش های کاربردی سایت مطلب مرتبط به مبحث ورود به پنل مدیریت را مطالعه کنید (برای دسترسی سریعتر می توانید از دکمه "قبلی" در انتهای همین صفحه نیز استفاده کنید).
<?php
//پیش فرض
$access = false;

//بررسی وضعیت دسترسی کاربر
include_once('access.php');

if($access === true) {
    //انتقال به پنل مدیریت
    header("Location: panel.php");
    exit;
}

//اگر فرم ارسال نشده باشد
if(!isset($check)) {
    $text = null;
    $username = null;
    $checked = null;
}
?>
<!DOCTYPE html>
<html lang="fa">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>وبگو | فرم HTML هوشمند ورود کاربر به پنل مدیریت سایت</title>
<!-- Webgoo.ir -->
<style>
body {
font-family: Tahoma, Geneva, sans-serif;
direction: rtl;
font-size: 12px;
line-height: 22px;
}
.error {
height: 30px;
width: 100%;
color: #dd000a;
}
</style>
</head>
<body>
<?php echo $text; ?>
<form action="login.php" method="post">
<label for="user">نام کاربری:</label>
<input name="username" id="user" type="text" value="<?php echo $username; ?>" maxlength="255" dir="ltr">
<label for="pass">کلمه عبور:</label>
<input name="password" id="pass" type="password" maxlength="255" dir="ltr">
<label for="remember">مرا بخاطر بسپار:</label>
<input name="remember" id="remember" type="checkbox" value="1"<?php echo $checked; ?>>
<input name="check" type="hidden" value="1">
<input type="submit" value="ورود به پنل">
</form>
<hr>
- قبل از ورود کاربر به پنل مدیریت سایت ابتدا باید اطلاعات اتصال به دیتابیس را در فایل config.php در آرایه config تعریف کرده باشیم، نام کاربری در لوکال هاست معمولا root و بدون کلمه عبور است.<br>
- اجرای صحیح این کد مستلزم ساخت دیتابیس، جدول users، ستون ها و درج نمونه اطلاعاتی است که در آموزش نحوه ساخت فرم عضویت سایت توضیح داده ایم.<br>
((در صورتی که آموزش نحوه ساخت فرم عضویت سایت را مطالعه نکرده و جدول users را با نمونه کاربر فرضی نساخته اید، لطفا ابتدا به بخش آموزش های کاربردی MySQL مراجعه و این مطلب را مطالعه کنید.))<br>
- همچنین باید جدول و ستون های مربوط به ثبت نشست ها در دیتابیس ایجاد شوند، برای این کار آدرس فعلی مرورگر را کپی کرده و با افزودن عبارت create.php در انتهای آدرس، در پنجره جدید این فایل را یک بار فراخوانی می کنیم، به طور مثال:<br>
http://localhost/php-mysql-signin-smart/create.php<br>
- دقت کنیم برای رمزنگاری کلمه عبور در مرحله عضویت کاربر از تابع password_hash استفاده کرده ایم، این تابع از نسخه PHP 5.5 در دسترس است، برای سازگاری نسخه های قدیمی تر کتابخه password_compat به کدها اضافه شده است.<br>
</body>
</html>
توضیح:
- این فایل در مقایسه با فایل index.php آموزش قبل تغییراتی داشته است، از جمله شروع نشست و اضافه شدن امکان بررسی وضعیت دسترسی کاربر در فایل access.php که در صفحه وارد (include) شده است.
- چک باکس یادآوری در فرم بالا با نام remember به صورت تگ input و نوع checkbox است.
- برای اینکه به طور پیش فرض چک باکس فعال بوده و به حالت انتخاب شده درآمده باشد پارامتر checked را به صورت متغیر با مقدار زیر ویرایش می کنیم:
$checked = ' checked="checked"';
اگر بخواهیم به طور پیش فرض تیک چک باکس غیر فعال باشد می توانیم این قسمت را null در نظر بگیریم.
- مقادیر value که برای فرم بالا و قسمت چک باکس عدد 1 در نظر گرفته شده فرضی است و می تواند هر مقداری باشد، به طور معمول مقادیر دیگری مانند true، ok و... نیز در نظر گرفته می شود، اما همان طور که در ادامه خواهیم دید نکته مهم این است که مقدار این فیلد یا وضعیت ارسال مقادیر آن را در سمت سرور و در کدهای PHP به عنوان متغیر از فرم HTML دریافت و بررسی خواهیم کرد تا از انتخاب شدن یا نشدن گزینه "یادآوری" توسط کاربر اطمینان حاصل کنیم.

بررسی اطلاعات ارسالی از فرم ورود در فایل login.php


پس از ارسال فرم توسط کاربر اطلاعات فیلدها به سرور منتقل شده و در این مرحله باید ببینیم نام کاربری و کلمه عبور با آنچه که پیشتر در قسمت ثبت نام در دیتابیس ثبت شده مطابقت دارد یا خیر، در صورت عدم تطابق ضمن نمایش پیغام خطا فرم ورود را مجددا بارگذاری می کنیم و در صورتی که اطلاعات ارسال شده با مقدار موجود تطابق داشت، ضمن تنظیم کوکی در مرورگر و ثبت مقدار سشن در دیتابیس کاربر را به فایل panel.php (فایل اصلی پنل مدیریت) منتقل خواهیم کرد، برای انجام این فرایندها در فایل login.php که در آموزش پیشین ساختیم تغییرات زیر را اعمال می کنیم:
<?php
//شروع نشست
session_name('panel');
session_start();

//تنظیم منطقه زمانی
date_default_timezone_set('Asia/Tehran');

//فایل تنظیمات اتصال به دیتابیس
include_once('config.php');

//تعریف توابع کلمه عبور در نسخه های پائین تر از PHP 5.5
if(!function_exists('password_hash')) {
    include_once('lib/password_compat.php');
}

//پیش فرض
$_SESSION['access'] = false;
$_SESSION['username'] = null;
$error = 0;
$text = null;
$checked = null;

//دریافت مقدار از فرم و تعریف متغیرها
@$username = $_POST['username'];
@$password = $_POST['password'];
@$remember = $_POST['remember'];
@$check = $_POST['check'];

/* بررسی معتبر بودن اطلاعات کاربر در صورت ارسال فرم */
if($check == 1) {
    //نام کاربری
    if(!isset($username) || empty($username)) {
        $error = 1;
        $text = "نام کاربری خود را وارد کنید!";
    } //کلمه عبور
    elseif(!isset($password) || empty($password)) {
        $error = 1;
        $text = "کلمه عبور خود را وارد کنید!";
    }

    //بررسی خطا
    if($error === 0) {
        //اتصال به دیتابیس
        $conn = mysqli_connect($config['host'], $config['db_user'], $config['db_pass'], $config['db_name']);

        if(!$conn) {
            echo "PHP & MySQL Connection: Error! " . mysqli_connect_errno() . ' - ' . mysqli_connect_error();
            exit;
        } else {
            //ایمن سازی پارامترها
            $username = mysqli_real_escape_string($conn, $username);

            //نام جدول
            $tbl_name = "users";

            //اانتخاب اطلاعات از جدول و ستون
            $sql = "SELECT `password` FROM $tbl_name WHERE `username` = '$username' LIMIT 1";
            $query = mysqli_query($conn, $sql);

            if(!$query) {
                echo "Selecting From Table $tbl_name: Error! " . mysqli_error($conn) . '<br>';
                exit;
            } else {
                //تعداد ردیف های انتخاب شده
                $count = mysqli_num_rows($query);

                if($count === 0) {
                    $error = 1;
                    $text = "نام کاربری یا کلمه عبور اشتباه است!";
                } else {
                    while($row = mysqli_fetch_array($query)) {
                        $db_hashed_password = $row['password'];

                        //تطبیق کلمه عبور
                        if(password_verify($password, $db_hashed_password)) {
                            //تنظیم متغیرهای سشن
                            $_SESSION['login'] = true;
                            $_SESSION['access'] = true;
                            $_SESSION['username'] = $username;
                            $_SESSION['remember'] = $remember;

                            //تعیین زمان کوکی یادآوری
                            if($remember == 1) {
                                //انقضای کوکی برای یک ماه
                                $cookie_time = 3600 * 24 * 30;
                            } else {
                                //انقضای کوکی برای نیم ساعت
                                $cookie_time = 1800;
                            }

                            //نام جدول
                            $tbl_name = "sessions";

                            //اانتخاب اطلاعات از جدول و ستون
                            $sql = "SELECT username FROM $tbl_name WHERE `username` = '$username' LIMIT 1";
                            $query = mysqli_query($conn, $sql);

                            if(!$query) {
                                echo "Selecting From Table $tbl_name: Error! " . mysqli_error($conn) . '<br>';
                                exit;
                            } else {
                                //تعداد ردیف های انتخاب شده
                                $count = mysqli_num_rows($query);

                                //پارامترهای سشن برای دیتابیس
                                $session_value = session_id();
                                $session_date = date('Y-m-d H:i:s', time() + $cookie_time);

                                //آپدیت یا ثبت اطلاعات نشست در دیتابیس
                                if($count == 1) {
                                    $sql = "UPDATE $tbl_name SET `remember` = '$remember', `session_value` = '$session_value', `session_date` = '$session_date' WHERE `username` = '$username' LIMIT 1";
                                    $query = mysqli_query($conn, $sql);
                                } else {
                                    $sql = "INSERT INTO $tbl_name(`username`, `remember`, `session_value`, `session_date`) VALUES('$username', '$remember', '$session_value', '$session_date')";
                                    $query = mysqli_query($conn, $sql);
                                }

                                if(!$query) {
                                    echo "Table $tbl_name Updating/Inserting: Error! " . mysqli_error($conn);
                                    exit;
                                }
                            }

                            //انتقال به پنل مدیریت
                            header("Location: panel.php");
                            exit;
                        } else {
                            $error = 1;
                            $text = "نام کاربری یا کلمه عبور اشتباه است!";
                        }
                    }
                }
            }
        }

        //پایان اتصال
        mysqli_close($conn);
    }
}

//بارگذاری مجدد فرم ورود در صورت بروز خطا یا فراخوانی مستقیم فایل لاگین
if($check != 1 || $error == 1) {
    if($error == 1) {
        $text = '<div class="error">' . $text . '</div>';
    }

    if($remember == 1) {
        $checked = ' checked="checked"';
    }

    include_once('index.php');
}
?>
توضیح:
- با ارسال اطلاعات فرم ورود به فایل login.php باید بررسی کنیم و ببینیم که نام کاربری و کلمه عبور ارسال شده با مقادیر موجود در دیتابیس مطابقت دارد یا خیر، در صورتی که اطلاعات صحیح باشد ضمن تنظیم متغیرهای سشن (login, access, username, remember) وضعیت نشست را در جدول sessions درج یا در صورت وجود به روزرسانی می کنیم.
- به دلیل استفاده از توابع header و session_start هیچ نوع خروجی نباید پیش از اجرای این توابع به مرورگر ارسال شود که شامل فضای خالی یا کاراکترهای نامرئی BOM (مخفف Byte Order Mark) نیز می شود، در غیر این صورت با پیغام خطای 
Warning: Cannot modify header information - headers already sent...
مواجه خواهیم شد، به همین دلیل در فایل login.php پیش از اجرای توابع header و session_start هیچ خروجی در سمت مرورگر چاپ نمی شود و با ایجاد انتقال از طریق تابع header و در نظر گرفتن پارامتر location کاربر را به طور خودکار به صفحه کاربری منتقل یا در صورت خطا فرم ورود (index.php) را در انتهای صفحه include می کنیم.
نکته: برای اطمینان بهتر است فایل ها را در برنامه ++Notepade اجرا و از قسمت Encoding گزینه Encoding in UTF-8 without BOM را انتخاب و مجددا فایل را ذخیره کنیم.
- مدت زمان اعتبار نشست در دو حالت متغیر خواهد بود، زمانی که کاربر تیک چک باکس یادآوری را انتخاب کرده باشد، این زمان را 30 روز معادل 2592000 ثانیه در نظر می گیریم (3600 ثانیه در 24 ساعت در 30 روز = 2592000 ثانیه)، 3600 میزان 1 ساعت به ثانیه است (60 ثانیه در 60 دقیقه)، اما اگر تیک یادآوری انتخاب نشده باشد زمان را 30 دقیقه معادل 1800 ثانیه در نظر می گیرم، این اعداد برای ثبت یا به روزرسانی اطلاعات نشست در دیتابیس و کوکی در مرورگر به کار می روند.
- برای محاسبه تاریخ و زمان از توابع date و time استفاده کرده ایم، تابع date تاریخ را با فرمت های متداول به فرض
2020-2-24 02:44:55
خروجی داده و تابع time تاریخ را به صورت برچسب زمان (Timestamp) به فرض 1581155023 با فرمت Unix خروجی می دهد.
- در صورت تطبیق صحیح اطلاعات ارسالی از فرم HTML با مقادیر موجود در دیتابیس، کاربر به فایل panel.php که در واقع فایل اصلی پنل کاربری سایت است منتقل می شود.

پنل کاربری سایت در فایل panel.php


فایل panel.php در واقع هسته اصلی بخش مدیریت سایتمان است که دیگر امکانات پنل در زیرمجموعه آن تعریف می شوند، در این فایل دو حالت متصور است:
در حالت اول اگر کاربر مستقیم از فرم ورود به این فایل ارجاع داده شده باشد یعنی هنوز کوکی یادآوری تنظیم نشده و باید ببینیم چک باکس "مرا بخاطر بسپار" انتخاب شده یا خیر، اگر چک باکس انتخاب شده باشد (متغیر سشن remember برابر 1 باشد) مدت زمان کوکی مشابه آنچه در مرحله لاگین مشاهده کردیم برابر با 30 روز (2592000 ثانیه) خواهد بود، در غیر اینصورت کوکی صرفا برای نیم ساعت (1800 ثانیه) تنظیم می شود.
در حالت دوم اگر کاربر قبلا به قسمت مدیریت ارجاع شده و در حال حاضر در پنل سایت حضور دارد، وضعیت دسترسی با متغیر سشن access بررسی می شود، این متغیر هم در فایل login.php و هم در فایل access.php تنظیم شده است، access.php فایلی است که وضعیت دسترسی کاربر را در هر درخواست زیر نظر دارد! (در ادامه این فایل را بررسی خواهیم کرد).
محتویات فایل panel.php با توجه به نیاز و ساختار برنامه می تواند متفاوت باشد، به عنوان مثال:
<?php
//پیش فرض
$access = false;
$cookie_time = 0;

//بررسی وضعیت دسترسی کاربر
include_once('access.php');

//فقط برای اولین ورود
if((isset($_SESSION['login']) && $_SESSION['login'] === true)) {
    //تنظیم کوکی یادآوری
    if(isset($_SESSION['remember']) && $_SESSION['remember'] === 1) {
        //تنظیم کوکی برای یک ماه
        $cookie_time = 3600 * 24 * 30;
        setcookie("panel", session_id(), time() + $cookie_time, "/");
    } else {
        //تنظیم کوکی برای نیم ساعت
        $cookie_time = 1800;
        setcookie("panel", session_id(), time() + $cookie_time, "/");
    }
}

//بررسی متغیرهای نشست
if((isset($_SESSION['access']) && $_SESSION['access'] === true)) {
    //پیام خوش آمدگویی و سایر کدهای پنل مدیریت
    echo 'Welcome To Control Panel!<br>User Name: ' . $_SESSION['username'];
    echo '&nbsp;[<a href="logout.php" title="Logout">Logout</a>]<br>';

    echo '<span id="show-time"></span>' . "\n";

    echo '<script>var countdown_timer; var server_time = ' . time() . '; var cookie_time = ' . (time() + $cookie_time) . ';
    window.onload = function(){countdown_timer = setInterval("reminedTime(\'show-time\');", 1000);}</script>'
. "\n";

    echo '<script src="script.js"></script>' . "\n";
} else {
    //دسترسی غیرمجاز
    header("HTTP/1.1 403 Forbidden");
    echo 'HTTP 403 Forbidden<br>Access Denied!';
    exit;
}
?>
توضیح:
- از تابع setcookie برای تنظیم کوکی جهت تعیین وضعیت دسترسی به بخش اعضاء سایت برای 30 روز یا نیم ساعت (بسته به انتخاب یا عدم انتخاب چک باکس یادآوری) استفاده می کنیم.
- تابع setcookie باید یک آرگیومنت به صورت زمان به ثانیه داشته باشد که نمایانگر مدت زمان اعتبار کوکی است، به فرض برای یک ساعت مقادیر 3600 ثانیه یا برای یک ماه معادل 2592000 ثانیه، بدین منظور ما از تابع time با افزودن یک مقدار عددی به آن استفاده کرده ایم.
time() + $cookie_time
- نام کوکی با تابع session_name و مقادیر کوکی - سشن با تابع session_id تنظیم می شود، همچنین برای تعیین مسیر (path) دسترسی کوکی پارامتر آخر را اضافه می کنیم، با تنظیم این قسمت به صورت "/" کوکی برای تمام دایرکتوری های زیرمجموعه سایت قابل دسترسی خواهد بود، در صورت عدم استفاده از پارامتر path به طور پیش فرض، کوکی فقط در دایرکتوری که آن را ایجاد کرده ایم قابل دسترسی و استفاده است، به فرض با تنظیم آن به صورت "/user/" کوکی فقط در این فولدر و دایرکتوری های زیرمجموعه آن قابل دسترسی و استفاده است از این رو بهتر است همواره از روش ذکر شده در نمونه کد بالا استفاده کنیم.
- در مقابل امکان "مرا به خاطر بسپار" قابلیت دیگری را نیز می توان برای پنل مدیریت سایت در نظر گرفت که معمولا به دلیل وجود حساسیت های خاص و ارتقاء امنیت صورت می گیرد، این امکان ایجاد یک سیستم خروج خودکار است که اگر به فرض مدت زمانی کاربر بدون فعالیت در صفحه باقی بماند نشست او خود به خود منقضی می شود، در این حالت حتی در موقعی که پنجره مرورگر هنوز باز است اعتبار نشست کاربر در سرور به پایان می رسد و او باید مجددا در پنل سایت وارد شود، این امکان معمولا با در نظر گرفتن مدت زمان کم برای اعتبار نشست در سیستم هایی که جنبه امنیت برایشان از اهمیت بالایی برخوردار است مانند سیستم تراکنش های بانکی و مالی، کنترل پنل های هاست، سیستم های آزمون آنلاین و...) به کار گرفته می شود.
- برای ایجاد شمارشگر معکوس (Countdown) و نمایش میزان زمان باقی مانده از اعتبار نشست کاربر دستورات PHP و JavaScript را به صورت ترکیبی استفاده کرده ایم، در سمت سرور تاریخ و زمان سرور و تاریخ اعتبار کوکی در تابع جاوا اسکریپتی reminedTime چاپ شده تا به عنوان آرگیومنت به این تابع داده شوند.
- با تابع setInterval به صورت پیوسته در هر ثانیه مجددا تابع reminedTime اجرا و آخرین زمان باقیمانده از اعتبار نشست محاسبه و در بلاک span با آی دی show-time خروجی داده می شود.

نمایش مدت زمان باقیمانده از اعتبار نشست با فایل script.js


تابع reminedTime که وظیفه نمایش مدت زمان باقیمانده از اعتبار نشست را به عهده دارد به صورت زیر در فایل script.js کدنویسی می کنیم:
//استخراج مدت زمان باقیمانده بر اساس اختلاف بین تاریخ سرور با تاریخ انقضای کوکی به ثانیه
var seconds = cookie_time - server_time;

//تابع برای محاسبه و نمایش زمان باقیمانده تا انقضای کوکی
function reminedTime(id){
    var days = Math.floor(seconds / 24 / 60 / 60);
    var hours_left = Math.floor((seconds) - (days * 86400));
    var hours = Math.floor(hours_left / 3600);
    var minutes_left = Math.floor((hours_left) - (hours * 3600));
    var minutes = Math.floor(minutes_left / 60);
    var remaining_seconds = seconds % 60;

    //خروجی
    var output = pad(days) + ":" + pad(hours) + ":" + pad(minutes) + ":" + pad(remaining_seconds) + ' Remained to Logout!';

    if(seconds == 0){
        clearInterval(countdown_timer);
        output = "You Need Login Again, Please Wait 5 Seconds!";
        setTimeout("goToURL('index.php');", 5000);
    } else{
        seconds--;
    }

    //چاپ خروجی در بلاک
    document.getElementById(id).innerHTML = output;
}

function pad(n){
    return (n < 10 ? "0" + n : n);
}

function goToURL(url){
    window.location.href = url;
}
توضیح:
- مدت زمان باقیمانده به ثانیه از حاصل تفریق زمان فعلی سرور و زمان انقضای کوکی به دست می آید، این زمان برای استفاده های بعدی در متغیر seconds مقداردهی شده است.
- در توضیح فایل panel.php گفتیم که تابع setInterval به صورت مداوم در هر ثانیه (1000 میلی ثانیه) تابع reminedTime را فراخوانی می کند، این کار تا زمانی که مقدار متغیر seconds از 0 بزرگتر باشد ادامه پیدا خواهد کرد.
- با 0 شدن مدت زمان باقیمانده، تابع clearInterval فراخوانی و اجرای پیوسته متغیر countdown_timer متوقف می شود.

بررسی وضعیت دسترسی کاربر با فایل access.php


برای بررسی وضعیت فعلی دسترسی کاربر از فایل access.php استفاده کرده ایم، به طور خلاصه این فایل وظیفه دریافت کوکی از مرورگر (در صورت وجود) و تطبیق آن با دیتابیس را بر عهده دارد، همچنین در این فایل نشست با تابع session_start شروع یا ادامه می یابد و اطلاعات دیتابیس با دستور UPDATE به روزرسانی می شود:
<?php
//شروع نشست اگر قبلا (در فایل لاگین) شروع نشده باشد
if(session_status() == PHP_SESSION_NONE || session_id() == '') {
    session_name('panel');
    session_start();
}

//تنظیم منطقه زمانی
date_default_timezone_set('Asia/Tehran');

//فایل تنظیمات اتصال به دیتابیس
include_once('config.php');

//پیش فرض
$access = false;
$panel_cookie = null;
$db_username = null;
$db_remember = 0;

//بررسی و دریافت مقدار کوکی از مرورگر
if(isset($_COOKIE['panel']) && !empty($_COOKIE['panel'])) {
    //مقدار کوکی
    $panel_cookie = $_COOKIE['panel'];

    //بررسی اعتبار کوکی و وضعیت یادآوری در دیتابیس
    $conn = mysqli_connect($config['host'], $config['db_user'], $config['db_pass'], $config['db_name']);

    if(!$conn) {
        echo "PHP & MySQL Connection: Error! " . mysqli_connect_errno() . ' - ' . mysqli_connect_error();
        //exit;
    } else {
        //نام جدول
        $tbl_name = "sessions";

        //تاریخ و زمان حاضر
        $now_date = date('Y-m-d H:i:s', time());

        //اانتخاب اطلاعات از جدول و ستون
        $sql = "SELECT username, remember FROM $tbl_name WHERE `session_value` = '$panel_cookie' AND `session_date` > '$now_date' LIMIT 1";
        $query = mysqli_query($conn, $sql);

        if(!$query) {
            echo "Selecting From Table $tbl_name: Error! " . mysqli_error($conn) . '<br>';
            exit;
        } else {
            //تعداد ردیف های انتخاب شده
            $count = mysqli_num_rows($query);

            //کوکی در دیتابیس وجود دارد
            if($count === 1) {
                //اگر کاربر از فرم ورود به پنل منتقل نشده باشد
                if(!isset($_SESSION['login'])) {
                    //بررسی مقدار یادآوری
                    while($row = mysqli_fetch_array($query)) {
                        $db_username = $row['username'];
                        $db_remember = $row['remember'];
                    }

                    //تنظیم متغیرهای سشن
                    $_SESSION['access'] = true;
                    $_SESSION['username'] = $db_username;
                    $_SESSION['remember'] = $db_remember;

                    //آپدیت کوکی یادآوری
                    if($db_remember === 1) {
                        //آپدیت کوکی برای یک ماه
                        $cookie_time = 3600 * 24 * 30;
                        setcookie("panel", session_id(), time() + $cookie_time, "/");
                    } else {
                        //آپدیت کوکی برای نیم ساعت
                        $cookie_time = 1800;
                        setcookie("panel", session_id(), time() + $cookie_time, "/");
                    }

                    //تاریخ و زمان جدید
                    $session_date = date('Y-m-d H:i:s', time() + $cookie_time);

                    //به روزرسانی زمان اعتبار نشست در دیتابیس
                    $sql = "UPDATE $tbl_name SET `session_date` = '$session_date' WHERE `username` = '$db_username' LIMIT 1";
                    $query = mysqli_query($conn, $sql);

                    if(!$query) {
                        echo "Updating Table $tbl_name: Error! " . mysqli_error($conn);
                        exit;
                    }
                }

                //دسترسی مجاز
                $access = true;
            } else {
                //دسترسی غیرمجاز
                $_SESSION['access'] = false;
                $access = false;
            }
        }
    }

    //پایان اتصال
    mysqli_close($conn);
} else {
    //دسترسی غیرمجاز
    $_SESSION['access'] = false;
    $access = false;
}
?>
توضیح:
- فایل access.php در صفحه index.php نیز استفاده شده و خود این فایل (در صورت بروز خطا در هنگام ورود) در فایل login.php وارد شده است، در این حالت برای جلوگیری از تداخل توابع نشست در فایل access.php ابتدا برقراری نشست را با شرط if و تابع session_status بررسی کرده ایم، در صورتی که تابع session_start قبلا اجرا شده باشد با اجرای مجدد این تابع و بروز تداخل خطای زیر را دریافت خواهیم کرد:
Notice: A session had already been started - ignoring session_start() in ... on line ...
- فایل access.php در ابتدای صفحات مورد نیاز وارد می شود و مواردی کلی پیکربندی مانند تنظیم منطقه زمانی و همچنین فایل config.php حاوی تنظیمات اتصال به دیتابیس در این فایل گنجانده شده است.
نکته: ساختار این برنامه جهت درک بهتر مطلب حالت ابتدایی و صرفا جنبه آموزشی دارد، هنگام کدنویسی برنامه های پیچیده می توانیم طوری ساختار را طراحی کنیم که چارچوب کار بهینه و به حداقل تعداد include نیاز باشد که معماری MVC (مخفف Model–View–Controller) یک نمونه متداول از آن است.

خروج از پنل کاربری با فایل logout.php


آخرین قسمت مورد نیاز برای پنل کاربری سایت در نظر گرفتن امکانی برای خروج استاندارد کاربر و منقضی شدن کامل نشست است، این قابلیت به طور معمولا با کلیک کاربر بر روی لینک یا دکمه خروج و فراخوانی فایل حاوی دستورات PHP اتفاق می افتد که در این آموزش به صورت دلخواه logout.php نامگذاری و با کدهای زیر تکمیل شده است:
<?php
//شروع نشست
session_name('panel');
session_start();

//فایل تنظیمات اتصال به دیتابیس
include_once('config.php');

//اتصال به دیتابیس
$conn = mysqli_connect($config['host'], $config['db_user'], $config['db_pass'], $config['db_name']);

if(!$conn) {
    echo "PHP & MySQL Connection: Error! " . mysqli_connect_errno() . ' - ' . mysqli_connect_error();
    exit;
} else {
    //نام جدول
    $tbl_name = "sessions";

    //پارامترهای سشن برای دیتابیس
    $session_username = $_SESSION['username'];

    //حذف اطلاعات سشن از دیتابیس
    $sql = "UPDATE $tbl_name SET `session_value` = null, `session_date` = null WHERE `username` = '$session_username' LIMIT 1";
    $query = mysqli_query($conn, $sql);

    if(!$query) {
        echo "Updating Table $tbl_name: Error! " . mysqli_error($conn);
        exit;
    }
}

//حذف کوکی از مرورگر
$cookie_time = 3600;
setcookie("panel", session_id(), time() - $cookie_time, "/");

//منقضی کردن و حذف اطلاعات نشست از سرور
session_unset();
session_destroy();

//انتقال به صفحه ورود
header("Location: index.php");
exit;
?>
توضیح:
- برای انجام خروج کامل باید اطلاعات نشست را در سه بخش دیتابیس، کوکی و فایل سشن  منقضی و حذف کنیم.
- در قسمت دیتابیس با اجرای دستور UPDATE مقادیر ستون های session_value و session_date را برای نام کاربری جاری به صورت null در نظر می گیریم.
- برای منقضی کردن کوکی کافی است با تابع setcookie و نامی مشابه یک کوکی با مدت زمان گذشته (مقدار منفی) تنظیم کنیم، در اینجا کوکی panel با مدت زمان منفی 3600 ثانیه یعنی یک ساعت قبل در نظر گرفته شده و به این ترتیب کوکی جدید جایگزین کوکی فعلی در مرورگر می شود و با توجه به تنظیم تاریخ گذشته مرورگر اطلاعات آن را در درخواست های بعدی ارسال نخواهد کرد.
- در آخرین مرحله باید اطلاعات نشست را در سرور منقضی و حذف کنیم، این اطلاعات شامل متغیرهای نشست و فایل فیزیکی حاوی سشن آی دی است که بر روی هارددیسک سرور ذخیره شده است، برای انجام این دو هدف توابع session_unset و session_destroy را فراخوانی می کنیم.

دانلود نمونه فایل های آموزش


برای جمع بندی کار و تست آنلاین یا آفلاین می توانیم فایل هایی که در این آموزش بررسی کردیم را از لینک زیر دریافت کنیم:
دانلود نمونه فایل های آموزش هوشمند سازی پنل ورود و خروج سایت با PHP و MySQL
نکته: امکانات مرتبط با پنل کاربری و سیستم ورود و خروج سایت جزء قسمت های حساس برنامه های تحت وب هستند، لذا توصیه می شود قبل از استفاده های کاربردی تا حد امکان کدها در محیط آزمایشی تست و تمام جوانب ممکن بررسی شود.
دسته بندی: آموزش کاربردی » MySQL
related مطالب بیشتر:
» جستجو در مطالب سایت با استفاده از MySQL Full-Text
» آموزش حذف گروهی اطلاعات از MySQL با استفاده از چک باکس
» تعویض کد امنیتی Captcha با Ajax و MySQL
» آموزش ساخت فرم تماس با PHP و MySQL
» نحوه رسم چارت و نمودار آماری با PHP و MySQL
commentنظرات (۸۲ یادداشت برای این مطلب ارسال شده است)
more یادداشت های جدید بر اساس تاریخ ارسال در انتهای یادداشت های موجود نمایش داده می شوند.
نویسنده: امین
۱۳:۴۸ ۱۳۹۴/۰۳/۳۱
سلام و خسته نباشید
برای حذف سشن و کوکی ثبت شده باید از چه تابعی استفاده کرد ؟
باتشکر
پاسخ: 
سلام
برای نشست از تابع
session_destroy();
و برای کوکی باید تاریخ انقضای آن را برای مدت زمانی قبلتر از حال حاضر تنظیم کنید، مثال:
setcookie(session_name(), session_id(), time() - 3600, "/");
نویسنده: امین
۱۸:۴۴ ۱۳۹۴/۰۴/۰۱
سلام و خسته نباشید
ممنون از پاسختون
ببخشید شیوه صحیح استفاده از نمونه زیر به چه شکلی هست؟
include"file_$num.php";
num$ یه متغییر هست که از طریق پرس و جو بدست میاد ولی استفاده ازش به شکل فعلی خطا نمایش میده
باتشکر فراوان از شما بابت پاسخگویی به سوالات بنده
پاسخ: 
سلام
به شکل زیر صحیح است:
include('file_'.$num.'.php');
نویسنده: amin
۱۴:۱۵ ۱۳۹۴/۰۴/۰۷
سلام مجدد
ببخشید من از کد زیر برای لاگین کردم استفاده میکنم و درست عمل میکنه فقط کوکی درست عمل نمیکنه در واقع بود و نبود setcookie فرقی نمیکنه !
$result = mysql_query ("SELECT * FROM use WHERE username = '$username' AND password = '$password'");
$count = mysql_num_rows($result);
if($count > 0){
$_SESSION['username'] = $username;
$_SESSION['password'] = $password;
$login_time=360000;//
setcookie(session_name(),session_id(),time()+$login_time,("/"));

echo 'ورود موفقیت آمیز';
}
else{
echo "نام کاربری یا رمز عبور درست نمی باشد";
}
پاسخ: 
سلام
این تابع وظیفه ایجاد یک کوکی در مرورگر را دارد و این چیزی نیست که به چشم دیده شود، باید به قسمت کوکی های مرورگر خود بروید و مقادیر موجود را در آنجا مشاهده کنید.
نویسنده: amin
۱۸:۴۴ ۱۳۹۴/۰۴/۰۷
سلام مجدد
منظورم این بود که مگه کوکی نباید باعث بشه که کاربر بعدا از لاگین تا زمان تعریف شده نیازی به لاگین کردن نباشه ؟ و مثلا تا 1 ماه (در صورت تعریف این زمان) بدون نیاز به لاگین و ثبت مجدد سشن بتونه از شرط زیر رد بشه ؟
if (isset($_SESSION['username'])){
دستور مورد نظر
}
اگر درست گفته باشم.
اما چنین نیست و بعد از چند دقیقه مجددا باید لاگین کرد و سشن برای کاربر مورد نظر ثبت شود .
با تشکر از پاسخگویی شما
پاسخ: 
سلام
ابتدا باید چک کنید که کوکی شما تنظیم می شود یا خیر، همچنین نحوه استفاده از تابع session_start اهمیت زیادی دارد که باید در ابتدای تمام صفحات باشد، در کل به نظر در بخشی از مراحل اشتباهی وجود دارد که اطلاعات از کوکی شما خوانده نمی شود یا کوکی وجود دارد، منتها در فرآیند کار تاثیری ندارد (بر اساس نوع دستورات شما)، در صورت عدم رفع مشکل، فایل هایتان را به صورت zip فشرده و به آدرس ایمیل ما (موجود در بخش تماس) ارسال و نتیجه را از همان طریق پیگیر باشید.
نویسنده: امین
۰۱:۵۹ ۱۳۹۴/۰۴/۱۱
سلام مجدد
با تشکر از راهنمایی که از طریق ایمیل انجام دادید
اما یک مساله !
همون طور که سشن رو ایجاد می کنید و بعد وجود اون رو از طریق isset بررسی میکنید
کوکی رو ایجاد میکنید اما در مراحل بعد هیچ بررسی نمیکنید که کوکی وجود دارد یا نه؟
نیاز به
if(isset($_COOKIE['name'])){
دستورات
}
نیست ؟
فرم فقط سشن رو بررسی میکنه که عملا کوکی چه تنظیم بشه چه نشه تاثیری در ورود بازدید کننده نداره ؟
من اطلاعات زیادی ندارم اما فکر کنم در این مثال که زدید کوکی چه ست بشه چه نشه تاثیری در ورود کاربر نداره و فقط سشن رو بررسی میکنه که عملا بعد از گذشت چند دقیقه کاربر مجددا باید یوزر و پسورد وارد کنه ! در واقع مدت زمان کوکی اگر برای یک ماه هم تنظیم شود کاربر چند دقیقه بعد باید یوزر و پسورد خود را وارد کند ؟!
پاسخ: 
سلام
خیر! کوکی و سشن دو مقوله مرتبط با هم هستند، زمانی که با تابع session_start یک نشست را آغاز می کنید، این تابع ابتدا وجود مقادیر کوکی ارسالی مرورگر را بررسی می کند، اگر کوکی با مقدار معتبر (منطبق با مقداری که به صورت فایل در سرور موجود است) ارسال شده باشد، نشست با همان اطلاعات ادامه پیدا می کند، یعنی اگر به فرض کاربر امروز وارد صفحه شده و کوکی برای مدت یک ماه برای او در مرورگر تنظیم شود، در مراجعات بعدی بلافاصله پس از شروع تابع session_start، مقدار کوکی بررسی می شود، اگر با مقدار session id موجود در سرور برابر بود، سشن معتبر است و بدون ورود مجدد با همان مقدار ادامه پیدا می کند، استفاده از دستور isset برای سشن به جهت نیاز برنامه است، یعنی باید بررسی کنیم که نشست معتبری در جریان است یا خیر، کوکی را خود تابع session_start بررسی و در صورت تنظیم، از مقادیر آن استفاده می کند!
نکته: در برنامه نویسی پیشرفته معمولا سیستم مشابه ای بر اساس دیتابیس طراحی می شود (مقدار سشن آی دی در دیتابیس نگهداری و مقدار کوکی با آن مقایسه می شود).
http://php.net/manual/en/function.session-start.php
نویسنده: محمد
۱۵:۵۱ ۱۳۹۴/۰۶/۲۱
سلام من برای لاگین شدن به سایت از سیشن ها استفاده کردم اما بعد خارج شدن از صفحات وبسایت یا بستن مرورگر سیشن ها منقضی نمی شن و این مشکل رو فقط با گوگل کروم دارم و خواهشا کمک کنید بفرمایید من چطور میتونم این معضل رو حل کنم ؟
پاسخ: 
سلام
ظاهرا این یک باگ در مرورگر کروم است! طبق اطلاعات موجود در وب، یک favicon (با فرمت ico) برای صفحه خود تنظیم کنید!
نویسنده: آکواحمدی
۰۰:۲۸ ۱۳۹۴/۰۹/۰۳
استاد سلام خسته نباشید آموزش بالا عالیه من کامل و دقیق همه رو نوشتم فقط قسمت کوکی مشکل دارم میخوام وقتی کاربر به سایتم لاگین میکنه کوکی بیاد یوزر و پسوردش و تو خودش به مدت 1 ساعت نگه داره و کاربر بتونه 1 ساعت توی سایت بدون ورود دوباره لاگین باشه اگه میشه کمکم کنید واقعا لازمش دارم واسه پروژه پایان نامم خیلی منونمم...
پاسخ: 
سلام
اگر آموزش را گام به گام و دقیق مطالعه کنید، توضیح این مورد به همراه نمونه کد گفته شده، کافی است کمی در رابطه با تابع session_start و setcookie اطلاعات قبلی داشته باشید، اگر با این وجود با مشکلی مواجه شدید، به صورت موردی مطرح کنید تا راهنمایی کنیم.
نویسنده: آکواحمدی
۱۳:۴۷ ۱۳۹۴/۰۹/۰۴
استاد سلام ببخشید من دقیقا نمیدونم منظورتون از session-name و session-id چی هست باید به جای اونها چی بزارم تا کوکی واسم ست بشه. من دقیق همین کدو مینویسم چک باکسم واسش تعریف کردم وقتی لاگین میکنم به صفحه ای که میخوام هدایت میشم و مشکلی ندارم فقط اگه از صفحه خارج بشم دوباره باید لاگین بشم تا به صفحه ای که میخوام برم. من میخوام بار اول که لاگین شدم دیگه تا 1ساعت نیازی به لاگین نباشه ممنون میشم جوابمو بدین اتشکر...
پاسخ: 
برای موارد فوق نیازی به تغییر کدها نیست، session_name و session_id جزء توابع درونی PHP هستند و به صورت خودکار نام و مقدار نشست فعلی را برمی گردانند و با تابع setcookie در قالب کوکی در مرورگر ذخیره می شود، لذا باید چک کنید و ببنید آیا کوکی در مرورگر ایجاد می شود + تاریخ انقضاء (Expire) کوکی چیست؟ در مرحله بعد در هر صفحه که نیازی به ورود مجدد نباشد باید ابتدا وجود کوکی را به صورت نمونه زیر بررسی کنید، اگر کوکی با مقدار معتبر برگشت داده شد، اطلاعات نمایش داده شود و در غیر این صورت کاربر به صفحه ورود هدایت شود:
<?php
session_start();
if(!isset($_SESSION['username']) || !isset($_SESSION['password'])){
header("location:login.php");
die();
}
else{
//کدهایی که کاربران عضو مجاز به اجرا یا دیدن آن باشند
}
?>
نکته: پیش از این آموزش باید مفهوم و استفاده کوکی را در وب درک کرده باشید، در غیر اینصورت توضیحات به هر نحوی که باشند، به نظر پیچیده و مبهم خواهد بود!
نویسنده: آکواحمدی
۰۰:۳۴ ۱۳۹۴/۰۹/۰۷
سلام مجدد استاد خیلی ممنون از توضیحتون واقعا مفید بود تغییراتی ایجادکردم الان کوکی واسم ست میشه یعنی وقتی میام به صفحه لاگین اگه یک بار لاگین کنم نام کاربری و پسورد رو واسم میزاره و برای دفعات بعدی نیازی نیست آنها را وارد کنم. استاد من میخواستم وقتی دوباره به صفحه لاگین میام دیگه صفحه لاگین واسم نمایش نده و مستقیم بره توی صفحه اصلیم امکانش هست راهنماییم کنین و کدهاشو بهم بدین ... ممنونتون میشم با تشکر.....
پاسخ: 
سلام
ذخیره نام کاربری و کلمه عبور جزء امکانات مرورگر است و ارتباطی به کوکی ندارد! سشن و کوکی مبحثی است که باید کاملا از مقدمات درک شود، بدون آشنایی با اصول کار، نمی توان راهنمایی بیشتری کرد، صرفا به عنوان نتیجه گیری:
وقتی از تابع session_start در صفحات PHP استفاده می کنید، مقدار سشن در سرور به صورت یک فایل و در مرورگر به صورت کوکی نگهداری می شود، هر زمان که نشست در جریان باشد (تابع session_start باید در تمام صفحات استفاده شود)، مقدار کوکی به سرور ارسال می شود و می توان در صورت وجود و معتبر بودن، کاربر را طبق نیاز به صفحات مختلف هدایت یا مقدار خروجی خاصی را نمایش داد، قاعدتا این بخش نیازمند کدنویسی و آشنایی قبلی شما با PHP است، در اینصورت آنچه در آموزش حاضر گفته شده برای فردی با میزان آشنایی متوسط با PHP کافی خواهد بود!
نویسنده: آکواحمدی
۱۸:۳۱ ۱۳۹۴/۰۹/۰۹
استاد امکانش هست فایلهامو واستون بفرستم لطف کنین یه نگاه بندازین ببینید مشکل کجاست؟
پاسخ: 
در صورتی که تعداد فایل ها زیاد نباشد، می توانید آنها را از طریق آدرس ایمیل (موجود در بخش تماس) به صورت یک فایل zip + فایل sql دیتابیس ارسال کنید تا بررسی گردد.
نویسنده: بهنام
۰۰:۲۳ ۱۳۹۴/۱۰/۱۷
سلام واقعاً شیوا و کاملا واضح اموزش دادید و برای اولین بار تونستم بدون هیچ مشکلی با کدهای پی اچ پی دست و پنجه نرم کنم... خیلی ممنونم...
یک سوال
وقتی کاربر لاگین میکنه، چطور میتونم کاری کنم که دیگه فرم ورود یا ثبت نام نمایش داده نشه و بجاش اطلاعات کاربر در همون قسمت بهمراه دکمه خروج نمایش داده بشه...؟
پاسخ: 
سلام
توضیح مطلب ساده نیست!، باید با نحوه کار دستورات شرطی (if، else و...) و نحوه مدیریت خروجی داینامیک در PHP آشنا باشید، در این صورت می توانید بررسی کنید که اگر کاربر وارد شده باشد، قسمت های اضافه در خروجی چاپ نشوند.
نویسنده: zahra
۰۹:۳۲ ۱۳۹۴/۱۰/۲۶
سلام ، کتابخانه
https://github.com/Gregwar/Captcha
رو دانلود کردم ولی نمی دانم کدام قسمت ها رو باید به برنامه اضافه کنم. البته بدون استفاده از composer.
پاسخ: 
سلام
متاسفانه امکان تست این موارد وجود ندارد، می توانید از نمونه کدهای موجود در فولدر demo استفاده کنید، همچنن در خصوص کاربرد use در PHP جستجو کنید.
نویسنده: آکواحمدی
۱۷:۴۷ ۱۳۹۴/۱۱/۱۲
استاد سلام خسته نباشید استاد من 3 تا فرم لاگین دارم که در صفحه نخست سایتم فرم اصلی قرار داره میخوام وقتی در این فرم لاگین میکنم فرمهای بعدی برداشته شه و دیگه نمایش داده نشه و امکان لاگین اوتوماتیک که در کدهای بالا توضیح دادی و میخوام واسه این 3 تا فرم پیاده سازی کنم ممنون میشم راهنماییم کنید با شکر.
پاسخ: 
سلام
همانطور که قبلا گفته شد، باید با سشن و کوکی کار کرده باشید، در این صورت می توانید وجود یک کوکی و سشن آی دی را بررسی و در صورت ست بودن (یعنی کابر اطلاعات ورود را قبلا صحیح وارد کرده)، در این صورت با دستورات شرطی (if، else، elseif) و به فرض include و... خروجی را به صورت دلخواه مدیریت کنید! بسیاری از مسائل برنامه نویسی صرفا در ابتدا نیاز به درک دستورات پایه (مانند نحوه تنظیم کوکی، سشن، نحوه بررسی ست بودن یا نبودن پارامترهای سشن و..) دارد، پس از درک این موضوع، اینکه چگونه ساختار برنامه ها را طراحی کنید عموما دلخواه و تا حدودی بسته به تجربه است، همچنین باید پس از درک اصول کار، وقت کافی برای تفکر بگذارید و سیستم مورد نیاز خود را ابتدا در تئوری طراحی و سپس اجرا (کدنویسی) کنید!، اگر مسائل به نظر پیچیده است، شاید دلیل آن عدم فراگیری از مقدمات و بصورت مرحله به مرحله باشد (نمی دانیم تا چه حدی با کدنویسی آشنا هستید، اما کار با کوکی و سشن جزء مباحث پشرفته است که قاعدتا باید از قبل مقدمات آن را فرا گرفته باشید)!
نویسنده: abolfazl
۱۴:۱۷ ۱۳۹۴/۱۱/۲۷
با سلام ضمن عرض تشکر از وب سایت و مطالب خوب شما
من توی نوشتن وب سایت مبتدی هستم دارم یه سایت طراحی می کنم و می خوام که توی قسمت فرم یک ایتم به نام ردیف داشته باشم که به صورت اتوماتیک عدد 1 تا ... رو به قسمت ورودی اختصاص بده مثلا 1... 2... 3... 4... یعنی هر سری که اطلاعات وارد میشه قسمت ردیف یک عدد به ترتیب اختصاص بده ممنون از راهنمایی هاتون
پاسخ: 
سلام
سوالتان چندپهلو است! لطفا از حالت خروجی نهایی مد نظر یک اسکرین شات تهیه کنید تا امکان درک دقیق سوال و ارائه راه حل وجود داشته باشد!
نویسنده: مینا
۲۳:۵۰ ۱۳۹۵/۰۸/۲۳
سلام خسته نباشید من سایتی نوشته ام که چندید کاربر با سطح دسترسی های مختلف دارم . مثلا یکی مدیر و یکی کاربر عادی هست سشنم درست است اما وقتی کاربر لاگین میکند بعد میتواند با آدرس صفحه مدیریت در آدرس بار وارد قسمت مدیریت شود. درصورتی که کدهایی که شما گفتین در صفحه مدیریت استارت کردم. یعنی کاربر عادی لاگین می کند بعد صفحه یوزر برایش باز میشود بعد اگر نوار ادرس خود را به admin.php تغییر دهد وارد قسمت مدیریت می تواند بشود
پاسخ: 
در صورت آشنایی و تسلط شما با مباحث مقدماتی، هیچ محدودیتی در اینکه این سیستم را در کجا و چگونه پیاده سازی کنید وجود ندارد! در واقع ما صرفا از قابلیت های اولیه و ذاتی PHP جهت آشنایی و درک مطلب استفاده کرده ایم که یک برنامه نویس وب می تواند متناسب با نیاز و هدف خود به شیوه های مختلف آن را بازنویسی کند!
more لطفا پیش از ارسال یادداشت نکات زیر را مد نظر داشته باشید:
- موارد غیرمرتبط با مباحث آموزش ها را در فرم منوی "تماس با ما" مطرح و پاسخ را از طریق ایمیل دریافت کنید.
- به سوالات کلی، مبهم و مشکلاتی که تلاشی برای رفع آن نکرده باشید پاسخ مختصر داده خواهد شد.
- کدها و اسکریپت های طولانی را ترجیحا در یک صفحه وب آنلاین قرار دهید تا امکان تست و بررسی وجود داشته باشد.
- از درج عناوین تبلیغاتی در فیلدها خودداری کنید، در صورتی که یادداشت تبلیغاتی تشخیص داده شود حذف خواهد شد.
- تمام یادداشت ها بررسی و زمانی جهت پاسخگویی در نظر گرفته می شود، لطفا از طرح سوالات متعدد خودداری کنید.





2 × 6
 refresh

آخرین دیدگاه ها
more برای دسترسی سریع به یادداشت مربوطه می توانید از لینک مطلب در کادر زیر استفاده کنید.
form علیرضا
در:
مفید و کاربردی مرسی
۱۴۰۰/۰۳/۳۱

form محمود
در:
سلام مهندس وقت بخیر دوباره به کمک شما نیاز پیدا کردم ، چگونه می توان استایل صوت به یک متن داد. به...
۱۴۰۰/۰۳/۳۰

form پرتو
در:
سلام استاد خسته نباشید قالبم درست شد خیلی ممنون یه خواهش دیگه هم ازتون داشتم اینکه یه بوردر برای تک به تک پست ها جداگانه...
۱۴۰۰/۰۳/۲۴

form بهنیا
در:
سلام خسته نباشید ببخشید چطوری میتونم برای خود وبسایتم یه لینک بسازم؟ کد خاصی داره؟
۱۴۰۰/۰۳/۲۴

form Raha
در:
سلام وقت بخیر چه جوری می تونم از دو تا function باهم استفاده کنم. مثلا میخوام توی مسیج باکس دوتا عدد دلخواه بدم...
۱۴۰۰/۰۳/۲۴

form رها
در:
سلام ممنون میشم اگه راهنماییم کنید من میخوام تو جاوا اسکریپت توی مسیج باکس بصورت اختیاری عدد بدم و جمع و تفریق انجام بشه. ...
۱۴۰۰/۰۳/۲۴

form محمد
در:
با عرض سلام و احترام مجدد پیرو کامنت قبلی که لطف کرده و توجه فرمودید آدرس سایت این هست: از توجه و راهنمایی‌های همیشگی...
۱۴۰۰/۰۳/۲۳

form محمد
در:
سلام وقت بخیر با سپاس از تیم محترم وبگو یک سوال داشتم از خدمتتون در عکسی که در آدرس با...
۱۴۰۰/۰۳/۲۲

form پرتو
در:
با سلام استاد من براتون ایمیل فرستادم لطفا ایمیل خود را چک کنید با تشکر
۱۴۰۰/۰۳/۲۱

form پرتو
در:
سلام خوبید خسته نباشید من یه کد قالبی دارم که میشه براتون بفرستم و شما تغییرش بدین من قالبم رو می خاستم اگه...
۱۴۰۰/۰۳/۲۰

form سید ارمیا حسینی
در:
سلام ببخشید عالی بود اما اگه می خواستم مثلا چیزی رو ایجاد کنم که مثلا کاربر بعد از ورود به صحفه 5 ثانیه بعد وارد...
۱۴۰۰/۰۳/۲۰

form الی
در:
سلام وقت بخیر من میخوام یه سایت طراحی کنم و در قسمت هدر یه گیف بذارم ولی هر کار می کنم گیف نمایش داده...
۱۴۰۰/۰۳/۱۸

form علیرضا حسینی
در:
دمتون گرم خسته نباشید خیلی عالی بود
۱۴۰۰/۰۳/۱۸

form حامدترابی
در:
سلام چند وقته که وبلاگ شهیدحسن ترابی گودرزی باز نمیشه ولی با vpn باز میشه. میشه راهنماییم کنید. ممنون میشم
۱۴۰۰/۰۳/۱۶

form mahdi
در:
سلام استاد این تابع در لوکال هم ایمیل ارسال میکنه هم فایل ضمیمه ، البته زمپ رو یه سری تغییرات باید داد و حساب ایمیل...
۱۴۰۰/۰۳/۱۲

form mahdi
در:
سلام وقت بخیر ، استاد عزیز اگر ما با تابع mail یه تابعی بنویسیم که در لوکال قابلیت ارسال هر نوع ایمیلی رو داشته باشه...
۱۴۰۰/۰۳/۱۲

form masood
در:
سلام وقتتون بخیر ببخشید من یک سوالی دارم اگر بخوایم تنظیماتی که برای id و class در نظر داریم رو تو یه...
۱۴۰۰/۰۳/۱۱

form mahdi
در:
استاد وقتشو دارید امشب ببینیدش مثلا در حد نیم ساعت که وقتتونم گرفته نشه؟
۱۴۰۰/۰۳/۱۰

form mahdi
در:
سلام استاد وقت بخیر،استاد عزیز من یه چارت با جاوااسکریپت نوشتم که سه تا نمودار میلیه ای و خطی و نقطه ای رو در بر...
۱۴۰۰/۰۳/۱۰

form پرتو
در:
وای من نمی تونم توی زمینه طراحی قالب های دیگ فعالیت کنم چون خیلی سختن فک نکنم بتونم اگر جایی می شناسید که قالب های...
۱۴۰۰/۰۳/۰۹

form پرتو
در:
سلام خسته نباشید شرمنده مزاحم شدم دوباره، می خاستم بپرسم می ارزه کسی وبلاگ در مورد قالب سازی بزنه یا اینکه نه نمی ارزه آخه...
۱۴۰۰/۰۳/۰۹

form یاس
در:
سلام میخواستم بدونم چجوری باید فایل متنی HTML دارای هایپرلینک را باز کند و محتوای آنرا بخواند و سپس هایپرلینک های آن را شناسایی کند...
۱۴۰۰/۰۳/۰۸

form sattar
در:
سلام، اون قسمتی که اعتبار سنجی ورود حروف فارسی هست مشکل داره یعنی کاربر رو اجبار به وارد کردن حروف فارسی میکنیم اما اگر مثلا...
۱۴۰۰/۰۳/۰۸

form mahdi
در:
سلام استاد ckeditor بهتره یا TinyMCE؟ من اینو ckeditor دیدم که راست چین چپ چین نداشت بعد استاد عزیز من یه چیزی رو...
۱۴۰۰/۰۳/۰۶

form پرتو
در:
ممنونم از شما که کدش رو دادید فقط یه سوال داشتم و اونم اینکه این کد رو در کدوم قسمت قالب قرار بدم و ایا...
۱۴۰۰/۰۳/۰۴

form mahdi
در:
سلام نه استاد عزیز نیازی نیست چون خودمم فکر میکنم لوگو رو باید از قبل مثلا با فتوشاپ آماده داشت و فقط میخواستم این امکانم...
۱۴۰۰/۰۳/۰۳

form پرتو
در:
سلام خواستم تشکر کنم از کدی که قبلا بهم داده بودید درست شد قالبم واقعا ممنونم ازتون یه چیز دیگه می خاستم بگم اینکه یه...
۱۴۰۰/۰۳/۰۳

form دانیال
در:
باسلام خیلی ممنون بابت مطالب عالیه سایتتون این مطلب هم مثل بقیه مطالب عالی بود
۱۴۰۰/۰۳/۰۳

form mahdi
در:
سلام استاد عزیز ، بله استاد اونطوری قرار میگیره وقتی تصویر از قبل مثلا با فتوشاپ شفاف شده باشه ، ولی اگر بخوایم یک عکس...
۱۴۰۰/۰۳/۰۳
  در انتظار بررسی: ۰
 پاسخگویی به سوالات ممکن است تا 24 ساعت زمان ببرد.