درود بر دوستان عزیز و همراهان گرامی ، وقتتون بخیر باشه و سلامت باشید.با اموزشی دیگر از سری آموزشهای php درخدمت شماهستم.امروز یه سیستم لاگین رو با php براتون آموزش می دم. چون یه بخشیه که فکر می کنم خیلی از مبتدی ها در اون مشکل دارن. بنابراین می تونید با استفاده از این آموزش، یه درک متوسطی از لاگین کردن و عملکرد کدها داشته باشید. امیدوارم به دردتون بخوره. در این آموزش برای لاگین کردن از سشن(session) استفاده می شه.

امروز یه سیستم لاگین رو با php براتون آموزش می دم. چون یه بخشیه که فکر می کنم خیلی از مبتدی ها در اون مشکل دارن. بنابراین می تونید با استفاده از این آموزش، یه درک متوسطی از لاگین کردن و عملکرد کدها داشته باشید. امیدوارم به دردتون بخوره. در این آموزش برای لاگین کردن از سشن(session) استفاده می شه.

این آموزش ما هفت بخش داره:

بخش اول : ایجاد فایل ها
بخش دوم: ایجاد پایگاه داده
بخش سوم: فایل config.php
بخش چهارم: فایل index.php
بخش پنجم: کدهای php در فایل index.php
بخش ششم: فایل user.php
بخش هفتم: فایل logout.php

این آموزش رو به دقت دنبال کنید و هر سوالی داشتید بپرسید.

بخش اول : ایجاد فایل ها
یه شاخه ی جدید در شاخه www بسازید با نام loginSample. در این سه تا فایل php ایجاد می کنید به نام های زیر:
کد (Text):

index.php
config.php
user.php
logout.php

بخش دوم: ایجاد پایگاه داده
یه پایگاه داده هم به نام لاگین بسازید و دستورات زیر رو در phpmyadmin وارد کنید:
PHP:

CREATE TABLE IF NOT EXISTS `users` (
`user_id` int(11) NOT NULL AUTO_INCREMENT,
`user_name` varchar(255) CHARACTER SET latin1 NOT NULL,
`user_pass` varchar(255) CHARACTER SET latin1 NOT NULL,
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_persian_ci AUTO_INCREMENT=1 ;

برای تست هم یه یوزر از phpmyadmin داخل جدول users وارد کنید.

بخش سوم: فایل config.php

ابتدا فایل config.php رو باز کنید و کدهای زیر رو در اون کپی کنید:
PHP:

توضیح کد:
PHP:

session_start();

وقتی می خواین با سشن ها کار کنید ابتدا باید این تابع رو فراخوانی کنید. این تابع باید اولین خط از دستورات شما باشه. یعنی قبل از این تابع شما هیچ خروجی یی نباید داشته باشین. پس از فراخوانی این تابع می تونید سشن هاتون رو سِت کنید.
PHP:

$db_host = “localhost”;
$db_name = “login”;
$db_user = “root”;
$db_pass = “”;

در این بخش هم ما متغیرهای مورد نیاز رو برای اتصال به پایگاه داده تعریف کردیم.

db_host = نام هاست دیتابیس که در لوکال هاست برابره با “localhost” البته در بیشتر سایت ها هم شما برای اتصال به پایگاه داده باید همین نام رو انتخاب کنید.
db_user = نام کاربری اتصال به پایگاه داده ست که برابره با “root”‏.
db_pass= که اگر چیزی تعریف نکرده باشین به طور پیش فرض null هستش(در لوکال هاست).
db_name = که نام پایگاه داده ی شماست که برابره با “login”.

بخش چهارم: فایل index.php
صفحه index.php رو که فرم لاگین در اون قرار داده شده رو باز می کنیم و کدهای زیر رو وارد می کنیم:

HTML:


<?php
if(isset($error))
{
echo '‘.$error.’‘;
}
?>

در این صفحه ما یه فرم ساختیم و روش ارسال اطلاعات رو post گذاشتیم و اکشن(محل ارسال داده های فرم) رو هم خالی گذاشتیم. خالی گذاشتن اکشن به معنای اینه که ما می خواهیم اطلاعات فرم رو به خود صفحه ارسال کنیم. می شه این کار رو به یه روش دیگه هم انجام داد که مقدار اکشن رو برابر کد زیر بزاریم:
[sourcecode language=’PHP’]

[/php]

در داخل این فرم ما دوتا تکست باکس گذاشتیم. اولی با نام username و نوع text و دومی با نام password و با نوع password. و کنار هر کدوم هم یه label گذاشتیم و متن داخلش و در انتها هم یه دکمه به نام ورود که اطلاعات فرم رو ارسال می کنه.

بخش پنجم: کدهای php در فایل index.php

حالا می رسیم به بخش کدهای php برنامه. در ابتدای همین صفحه و قبل از تگ html این کدها رو وارد کنید:
PHP:

۰)
{
$_SESSION[‘user’] = $username;
header(“location: user.php”);
}
else
{
$error = “نام کاربری یا گذرواژه اشتباه است.”;
}
}
}

?>

توضیح کد ها:
PHP:

include_once(“config.php”);

در این بخش ما درواقع محتویات فایل config.php رو وارد کردیم در این صفحه. از این دستور و دستور require که دقیقاً مثل همین عمل می کنه می شه به دو روش استفاده کرد:
PHP:

include(“yourFile”);
include_once(“yourFile”);
require (“yourFile”);
require _once(“yourFile”);

با حالت ۲ و ۴ شما می تونید فقط یک بار یک فایل رو اینکلود کنید. از حالت ۱ و ۳ برای فایل هایی استفاده می کنن که ممکنه چند بار در یک صفحه استفاده بشه.

PHP:

if(isset($_POST[‘username’]))
{
//your code
}

بخش بالا رو برای این نوشتیم که چک کنیم که آیا کلید ورود زده شده و مقداری ارسال شده یانه؟ در واقع اگر برای اولین بار وارد صفحه شده باشید جواب این شرط منفی ست و دستورات داخل اون کار نمی کنن. بعد که نام کاربری و رونوشتید و وارد شدید این شرط فعال شده. حالا در داخل این شرط این دستورات هستن:
PHP:

$db_link = mysql_connect($db_host, $db_user, $db_pass) or die(“خطا در اتصال به پایگاه داده”);
mysql_select_db($db_name, $db_link) or die(“خطا در انتخاب پایگاه داده”);

در خط اول ما با تابع mysql_connect به دیتابیس وصل شدیم. وقتی به دیتابیس وصل می شین مقدار بازگشتی رو که کلید دیتابیس ماست داخل یه متغیر ($db_link) می ریزیم و با ()or die هم گفتیم که اگر اتصال برقرار نشد این پیام خطا رو نمایش بده. برای تست می تونید نام هاست دیتابیس رو که localhost هستش و در فایل config تعریف کردیم رو اشتباه وارد کنید و نتیجه رو ببینید.
دستور mysql_connect سه تا متغیر می گیره که در فایل config.php تعریف کردیم. نام هاست دیتابیس ، نام کاربری دیتابیس و گذرواژه ی دیتابیس.
در خط بعدی هم پایگاه داده مون رو انتخاب کردیم و با or_die هم خطای مورد نظر رو چاپ می کنیم. این دستور هم دوتا متغیر می گیره که اولی نام دیتابیس و دومی کلید دیتابیس هستش که در خط بالایی تعریف شد.

PHP:

$username = trim($_POST[‘username’]);
$password = trim($_POST[‘password’]);

مقدارهایی که در صفحه ارسال می شن رو هر کدوم در متغیر مورد نظر خودمون ریختیم. دستور ()trim هم کاراکترهای اسپیس رو از ابتدا و انتهای نام کاربری و گذرواژه حذف می کنه.

PHP:

if(empty($username) || empty($password))
{
$error = “نوشتن نام کاربری و گذرواژه الزامی ست.”;
}
else
{
$sql = “SELECT * FROM `users` WHERE `user_name` = ‘”.$username.”‘ AND `user_pass` = ‘”.$password.”‘”;
$result = mysql_query($sql) or die(“خطا در انجام درخواست”);
$userExist = mysql_num_rows($result);
if($userExist > 0)
{
$_SESSION[‘user’] = $username;
header(“location: user.php”);
}
else
{
$error = “نام کاربری یا گذرواژه اشتباه است.”;
}
}

در این شرط این رو بررسی می کنیم که آیا مقدار نام کاربری و گذرواژه ی ارسالی خالی هستند یا نه.
اگر خالی بود:
PHP:

$error = “نوشتن نام کاربری و گذرواژه الزامی ست.”;

یه متغیر به نام خطا ایجاد کن و مقدارش رو قرا بده با خطای مورد نظر.

اگر خالی نبود:
PHP:

$sql = “SELECT * FROM `users` WHERE `user_name` = ‘”.$username.”‘ AND `user_pass` = ‘”.$password.”‘”;
$result = mysql_query($sql) or die(“خطا در انجام درخواست”);
$userExist = mysql_num_rows($result);
if($userExist > 0)
{
$_SESSION[‘user’] = $username;
header(“location: user.php”);
}
else
{
$error = “نام کاربری یا گذرواژه اشتباه است.”;
}

درخواست دیتابیس رو درست می کنیم. به این صورت که نام کاربری و گذرواژه رو که از کاربر گرفتیم داخل کوئری قرار می دیدم و با تابعmysql_query نتیجه ی برگشتی از پایگاه داده رو درش ذخیره می کنیم.

بعد با تابع mysql_num_rows تعداد سطر هایی رو که این نتیجه به ما می ده داخل یه متغیر userExist$ می ریزیم.
بعد چک می کنیم که اگر userExist$ بزرگتر از صفر بود ( یعنی یه سطر یا بیشتر (که این هم درست نیست که چن تا یوزر به یه نام باشه ولی فعلن این رو داشته باشید) سشن user رو برابر با username$ قرار بده ( که از خود کاربر گرفتیم به عنوان نام کاربری:
PHP:

$_SESSION[‘user’] = $username;

بعد با خط پایین کاربر رو می فرستیم به صفحه ی کاربر:
PHP:

header(“location: user.php”);

اگر هم مقدار سطر هایی که درخواست sql برامون برگردوند صفر بود که یعنی کاربری به این نام وجود نداره و متغیر error$ رو با مقدار مورد نظر پر می کنیم.

حالا اگه کاربر وجود نداشته باشه و ما مقدارش رو هم با خطای مورد نظر پر کنیم باید این خطا رو به کاربر نشون بدیم. در جدولی که طراحی کرده بودیم یه بخش بود که کامنت html گذاشته بودیم:
HTML:

به جای اون کد زیر رو قرار بدین:

PHP:

<?php
if(isset($error))
{
echo '‘.$error.’‘;
}
?>

یعنی اگر خطایی ایجاد شده، خطا رو نشون بده. با رنگ قرمز حتی!

بخش ششم: فایل user.php
PHP:

خروج

خروج

فقط یه توضیح مختصر می دم در این مورد:
PHP:

if(!isset($_SESSION[‘user’]))
{
header(“location: index.php”);
}
$username = $_SESSION[‘user’];

اگر سشن ست نشده بود، اجازه نمی ده کاربر صفحه رو ببینه ( یعنی حتمن باید لاگین کرده باشه). باز هم یعنی اگه شما آدرس فایل رو از address bar وارد کنید ، صفحه index.php رو خواهید دید. اگر هم که لاگین کرده بود نامش رو قرار می ده در یه متغیر و پایین هم یه بخش قرار دادیم برای خوش آمدگویی و زیرش هم یه لینک برای خروج.

بخش هفتم: فایل logout.php
PHP:

خط سوم سشن ایجاد شده رو حذف می کنه و خط چهارم کاربر رو منتقل می کنه به صفحه اول.

برای دانلود پروژه می تونید از لینک زیر استفاده کنید:
دانلــــــــــــــــــــــود

به همین راحتی و به همین خوشمزگی تونستیم یه بخش لاگین برای سایتمون بنویسیم. البته این رو هم عنوان کنم که در این آموزش ما فقط کاربر رو منتقل کردیم در حالی که باید تمامی تمهیدات امنیتی رو در نظر بگیریم که مبادا سایتمون هک بشه. ولی چون این یه آموزش مبتدی هستش برای نشون دادن روش لاگین کردن، بنابراین بخش امنیت رو به جلسه های بعدی موکول می کنیم.

امیدوارم به کار قشنگتون ادامه بدید .

این سیستم برای شروع خوبه ولی
در عمل ۳ تا مشکل داره

۱٫ خطر SQL Injection جدی :
که میشه با دادن نام کاربری و رمز عبور مخرب مشکل درست کرد
که ۲ تا راه حل داره

—– راه حل اول که بشترین امنیت رو داره :
اینه که به فقط اجازه استفاده از A-z 0-9 و _-. رو بدهید

به جای
PHP:

if(empty($username) || empty($password))
{
$error = “نوشتن نام کاربری و گذرواژه الزامی ست.”;
}

بگذارین

PHP:

if(!preg_match(‘/^([a-z0-9_\.\-]{6,35})$/i’,$username) || empty($password))
{
$error = “نوشتن نام کاربری و گذرواژه الزامی ست.”;
}

و رمز عبور هم md5 بکنید تا هم امنیت داشته باشه هم نیازی به چک کردن نداشته باشه
یعنی

به جای
PHP:

$sql = “SELECT * FROM `users` WHERE `user_name` = ‘”.$username.”‘ AND `user_pass` = ‘”.$password.”‘”;

بگذارین
PHP:

$sql = “SELECT * FROM `users` WHERE `user_name` = ‘”.$username.”‘ AND `user_pass` = ‘”.md5($password).”‘”;

— راه حل دوم استفاده از یک تابع ضد تزریق هست
در کد زیر یک تابع خوب رو آوردم
PHP:

function mysql_prep($value){
$magic_quotes_active = get_magic_quotes_gpc();
$new_enough_php = function_exists(“mysql_real_escape_string”); // i.e. PHP >= v4.3.0
if ($new_enough_php)
{ // PHP v4.3.0 or higher
// undo any magic quote effects so mysql_real_escape_string can do the work
if ($magic_quotes_active)
{
$value = stripslashes($value);
}
$value = mysql_real_escape_string($value);
} else
{ // before PHP v4.3.0
// if magic quotes aren’t already on then add slashes manually
if (!$magic_quotes_active)
{
$value = addslashes($value);
}
// if magic quotes are active, then the slashes already exist
}
return $value;
};

و این تابع رو به این شکل استفاده کنید
PHP:

$sql = “SELECT * FROM `users` WHERE `user_name` = ‘”.mysql_prep($username).”‘ AND `user_pass` = ‘”.mysql_prep($password).”‘”;

مشکل دوم

Session hijacking است
http://en.wikipedia.org/wiki/Session_hijacking
که برای یاد گیری مبارزه به این تاپیک مراجع کنید
http://forum.majidonline.com/showthread.php?t=79624

مشکل سوم
که بستگی به خود شما داره
اینه که می تونین برای لاگین کد امنیتی بگذارین
و یا اینکه ۳ شرط زیر رو بگذارین
۱٫ اگر نام کاربری درست بود
۲٫ سپس رمزعبور ۵ بار اشتباه وارد شد
۳ . سیستم ۱۵ دقیقه قفل شود

این تاپیک رو هم ببینید (مهم)
http://forum.majidonline.com/showthread.php?t=129726

این رو هم عنوان کنم که در این آموزش ما فقط کاربر رو منتقل کردیم در حالی که باید تمامی تمهیدات امنیتی رو در نظر بگیریم که مبادا سایتمون هک بشه. ولی چون این یه آموزش مبتدی هستش برای نشون دادن روش لاگین کردن، بنابراین بخش امنیت رو به جلسه های بعدی موکول می کنیم.

خودم که عنوان کردم که کاملن آموزشی برای درک الگوریتم لاگین کردنه
وگرنه هیچ کاری برای امنیت توی این آموزش انجام نشده

همون طوری که k2-4u عزیز عنوان کردن باید تمامی موارد حل بشه

نکات دیگه ای هم هست که می شه به نکته های k2-4u اضافه کرد:
۱- به قول k2-4u گذاشتن کد کپچا ۱۰۰٪ ضروری هستش. حتمن باید استفاده بشه
۲- چک کردن این که فرم از طریق سایت خودتون ارسال می شه نه از یه جای دیگه ( درواقع هکر می تونه یه فرمی تو صفحه ی خودش طراحی کنه و هی به صفحه شما ارسال کنه که از طریق کپچا هم تا حدودی جلوش گرفته می شه)
۳- برای xss و … هم تمهیداتی باید اندیشید که اگه می خواین کاملن مسلط بشین به این بخش به این سایت هم می تونید سر بزنید:
امنیت در php
اینجا هم مطالب خوبی عنوان شده در رابطه با امنیت:
امنیت در php ۲