آموزش قدم به قدم ساخت لاگین

سیستم لاگین با php

درود بر دوستان عزیز

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

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

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

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

بخش اول : ایجاد فایل ها
یه شاخه ی جدید در شاخه www بسازید با نام loginSample. در این سه تا فایل php ایجاد می کنید به نام های زیر:
کد:
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();

	$db_host = "localhost";
	$db_name = "login";
	$db_user = "root";
	$db_pass = "";

?>

توضیح کد:
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:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Login Sample - http://Minerva-se.com/</title>
</head>

<body>
<br /><br /><br />

<form action="" method="post">
  <table width="400" border="0" align="center" cellpadding="10" cellspacing="0" style="border:1px solid #CCC;">
    <tr>
      <td colspan="2" align="center" dir="rtl">
      <!-- محل نمایش خطای ورود -->
       <?php
	   		if(isset($error))
			{
				echo '<font color="#FF0000">'.$error.'</font>';
			}
	   ?>
      </td>
    </tr>
    <tr>
      <td width="192" align="right"><input type="text" name="username" id="username" /></td>
      <td width="188" align="left" dir="rtl"><label>نام کاربری :</label></td>
    </tr>
    <tr>
      <td align="right"><input type="password" name="password" id="password" /></td>
      <td align="left" dir="rtl"><label>گذرواژه :</label>
      </td>
    </tr>
    <tr>
      <td colspan="2" align="center"><input type="submit" name="button" id="button" value="  ورود  " /></td>
    </tr>
  </table>

</form>
</body>
</html>

بقیه اش رو هم ادامه می دم
هر چند این مطلب رو کامل تو وبلاگم زدم ولی الان باید برم وقت ندارم

میام کاملش می کنم
روز همگی خوش
 
در این صفحه ما یه فرم ساختیم و روش ارسال اطلاعات رو post گذاشتیم و اکشن(محل ارسال داده های فرم) رو هم خالی گذاشتیم. خالی گذاشتن اکشن به معنای اینه که ما می خواهیم اطلاعات فرم رو به خود صفحه ارسال کنیم. می شه این کار رو به یه روش دیگه هم انجام داد که مقدار اکشن رو برابر کد زیر بزاریم:
[sourcecode language='PHP']
<?php $_SERVER['PHP_SELF'] ?>
[/php]

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

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

حالا می رسیم به بخش کدهای php برنامه. در ابتدای همین صفحه و قبل از تگ html این کدها رو وارد کنید:
PHP:
<?php
	include_once("config.php");
	if(isset($_POST['username']))
	{
		$db_link = mysql_connect($db_host, $db_user, $db_pass) or die("خطا در اتصال به پایگاه داده");
		mysql_select_db($db_name, $db_link) or die("خطا در انتخاب پایگاه داده");
		
		$username = trim($_POST['username']);
		$password = trim($_POST['password']);
		
		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:
include_once("config.php");
در این بخش ما درواقع محتویات فایل config.php رو وارد کردیم در این صفحه. از این دستور و دستور require که دقیقاً مثل همین عمل می کنه می شه به دو روش استفاده کرد:
PHP:
include("yourFile");
include_once("yourFile");
require ("yourFile");
require _once("yourFile");
با حالت 2 و 4 شما می تونید فقط یک بار یک فایل رو اینکلود کنید. از حالت 1 و 3 برای فایل هایی استفاده می کنن که ممکنه چند بار در یک صفحه استفاده بشه.

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:
...
    <tr>
      <td colspan="2" align="center" dir="rtl">
      <!-- محل نمایش خطای ورود -->
      </td>
    </tr>
...

به جای اون <!-- محل نمایش خطای ورود --> کد زیر رو قرار بدین:

PHP:
       <?php
	   		if(isset($error))
			{
				echo '<font color="#FF0000">'.$error.'</font>';
			}
	   ?>
یعنی اگر خطایی ایجاد شده، خطا رو نشون بده. با رنگ قرمز حتی!

بخش ششم: فایل user.php
PHP:
<?php
	include_once("config.php");
	if(!isset($_SESSION['user']))
	{
		header("location: index.php");
	}
	
	$username = $_SESSION['user'];
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>User Page</title>
</head>

<body  dir="rtl">
<label>خوش آمدید <b><?php echo $username; ?></b></label>
<br /><br />

<a href="logout.php">خروج</a>
</body>
</html>

<label>خوش آمدید <strong> </strong></label>

<a href="logout.php">خروج</a>
فقط یه توضیح مختصر می دم در این مورد:
PHP:
	if(!isset($_SESSION['user']))
	{
		header("location: index.php");
	}
	$username = $_SESSION['user'];
اگر سشن ست نشده بود، اجازه نمی ده کاربر صفحه رو ببینه ( یعنی حتمن باید لاگین کرده باشه). باز هم یعنی اگه شما آدرس فایل رو از address bar وارد کنید ، صفحه index.php رو خواهید دید. اگر هم که لاگین کرده بود نامش رو قرار می ده در یه متغیر و پایین هم یه بخش قرار دادیم برای خوش آمدگویی و زیرش هم یه لینک برای خروج.

بخش هفتم: فایل logout.php
PHP:
<?php 
include_once("config.php");
session_destroy();
header("location: index.php");
?>

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

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


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

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

Masoud1365

مدیر انجمن
خیلی خوب بود . من همه کدها رو نخوندم ولی یه چیزی که به نظرم اومد اینه که اگر پسوورد هش بشه و داخل دیتا بیس سیو بشه بهتره :wink:
ممنون بابت آموزشت.

موفق و پیروز باشید.
 

k2-4u

Well-Known Member
این سیستم برای شروع خوبه ولی
در عمل 3 تا مشکل داره

1. خطر SQL Injection جدی :
که میشه با دادن نام کاربری و رمز عبور مخرب مشکل درست کرد
که 2 تا راه حل داره

----- راه حل اول که بشترین امنیت رو داره :
اینه که به فقط اجازه استفاده از 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

مشکل سوم
که بستگی به خود شما داره
اینه که می تونین برای لاگین کد امنیتی بگذارین
و یا اینکه 3 شرط زیر رو بگذارین
1. اگر نام کاربری درست بود
2. سپس رمزعبور 5 بار اشتباه وارد شد
3 . سیستم 15 دقیقه قفل شود

این تاپیک رو هم ببینید (مهم)
http://forum.majidonline.com/showthread.php?t=129726
 
این رو هم عنوان کنم که در این آموزش ما فقط کاربر رو منتقل کردیم در حالی که باید تمامی تمهیدات امنیتی رو در نظر بگیریم که مبادا سایتمون هک بشه. ولی چون این یه آموزش مبتدی هستش برای نشون دادن روش لاگین کردن، بنابراین بخش امنیت رو به جلسه های بعدی موکول می کنیم.

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

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

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

موفق باشید
 

htarahi

Member
ارور !!!

سلام
در ابتدا تشکر می کنم ازمطالب مفید این بخش و دوستانی که زحمت نوشتن مطالب رو بر عهده داشتند.
من تمامی مراحل رو مطابق توضیحات جلو رفتم اما با ارور زیر روبرو شدم :shock::
Warning: mysql_connect() [function.mysql-connect]: Access denied for user 'me'@'localhost' (using password: YES) in C:\wamp\www\loginSample\index.php on line 5
خطا در اتصال به پایگاه داده
لطفاً راهنمایی کنید ...:cry::cry::cry:
 

htarahi

Member
ایول
ایول
ببخشید دیگه
تازه کاریه و 1000 درد شرعی:green:
من برا root پسورد گذاشته بودم
اما مشکل از اینجا ناشی می شد که توی config.php اینو در نظر نگرفته بودم.
 

htarahi

Member
اما یه مشکل تازه:-?
الان صفحه ی لاگین در حالی باز میشه که کادر username خالیه اما کادر password با 3 تا * میاد !!!
درضمن پس از زدن id و pass ی که در جدول login ساختم میگه :
نوشتن نام کاربری و گذرواژه الزامی ست.
و در برنامه وقتی if مربوطه رو بایپس می کنم میگه :
نام کاربری یا گذرواژه اشتباه است.
یعنی یه جورایی با password-م مشکل داره.
id رو گذاشتم me و pass رو 111
 
ای دی رو گذاشتی me?????
یوزر رو باید بزاری me
آی دی رو پر نکن خودش پر می کنه phpmyadmin
 

htarahi

Member
و اما یه سوال دیگه هم دارم
من الان با phpmyadmin کار می کنم
3 تا database دارم و در دیتابیس login ،دو تا جدول.
دستور :
کد:
$db_name = "login";
میره وارد دیتابیس login میشه اما از کجا جدول رو تشخیص میده ؟؟؟
مثلاً جدول 1 و 2 رو داریم و توی هردوشون هم username ی به نام me هست اما با password های متفاوت!
آیا نباید دستور رو کاملترش کرد ؟
 

htarahi

Member
ای دی رو گذاشتی me?????
یوزر رو باید بزاری me
آی دی رو پر نکن خودش پر می کنه phpmyadmin

نه نه
عذر می خوام
سوتی شد
اینجوری پر کردم :
کد:
<?php 
    session_start(); 

    $db_host = "localhost"; 
    $db_name = "login"; 
    $db_user = "root"; 
    $db_pass = "php"; 

?>
و اما مشخصات من در phpmyadmin :
root : php
me : 111​
 

جدیدترین ارسال ها

بالا