PDA

View Full Version : سوال: جلوگیری از ثبت داده های تکراری در MYSQL



meysam1366
جمعه 12 اردیبهشت 1393, 11:50 صبح
سلام دوستان

ببخشید مزاحم شدم

میخواستم بدونم که چه جوری باید از ثبت اطلاعات تکراری توی پایگاه داده جلوگیری کنم؟

الان وقتی صفحه رو رفرش می کنم مجدد اطلاعات توی پایگاه داده ثبت میشه

ممنون

***BiDaK***
جمعه 12 اردیبهشت 1393, 12:21 عصر
یک راهش استفاده از هدره.
وقتی عملیات با موفقیت انجام شد ادامه ی کد , صفحتو دوباره با هدر فراخوانی کن:


header('location: currentPage.php');
exit();

meysam1366
جمعه 12 اردیبهشت 1393, 14:06 عصر
سلام دوست عزیز

ممنون از راهنماییتون

ولی با این کد انجام دادم نشد چون یکبار از کد در بخش دیگه ای استفاده کردم در همین صفحه

colors
جمعه 12 اردیبهشت 1393, 14:34 عصر
در بالای صفحه یه سشن مثلا به اسم form_submit_token بسازید و یه مقدار رندم رو مثلا با تابع rand بهش بدید. (1,5000)rand که در هر بار لود پیج, مقدار جدیدی داشته باشه. تو فرم مربوطه یه input از نوع hidden بزارید و valueش رو برابر مقدار سشنی بزارید که اول صفحه ساختید. وقتی که فرم رو ارسال کردید, چک کنید ببینید مقدار فیلد مخفی با مقدار سشنی که از قبل ساختید برابر هست یا نه. اگر برابر بود ادامه دستورات و اگر نبود به کاربر خطا میدم.
در این صورت وقتی صفحه رو رفرش کنید, برنامه خطا میده, چون با رفرش مقدار داخل سشن تغییر میکنه ولی مقدار فیلد مخفی همون مقدار قبلی هستش.

***BiDaK***
جمعه 12 اردیبهشت 1393, 14:34 عصر
چی؟کدتونو بذارید...
اگر مشکل هدره از این کد استفاده کنید:


header('location: currentPage.php');
exit('<meta http-equiv="Refresh" content="0; url="currentPage.php">');

---------------
راه دیگم همینیه که سامان گفت.جلوی csrf هم گرفته میشه.

meysam1366
جمعه 12 اردیبهشت 1393, 15:06 عصر
چی؟کدتونو بذارید...
اگر مشکل هدره از این کد استفاده کنید:


header('location: currentPage.php');
exit('<meta http-equiv="Refresh" content="0; url="currentPage.php">');

---------------
راه دیگم همینیه که سامان گفت.جلوی csrf هم گرفته میشه.

سلام

این کد صفحه signup.php


<!DOCTYPE html>
<html>
<head>
<title>اطلاعات ثبت نام</title>
<meta charset="UTF-8" />
</head>
<body>
<?php
// اطلاعات ثبت نام
$id = '';
$name = $_POST['name'];
$family = $_POST['family'];
$father = $_POST['father'];
$user = $_POST['user'];
$pass = md5($_POST['pass']);

if (empty($id) && empty($name) && empty($family) && empty($father) && empty($user) && empty($pass) == '') {
header('Location: index.php');
exit();
}

// connet database & insert
$server = 'localhost';
$username = 'root';
$password = '';
$db = 'signup';
$conn = @mysql_connect($server, $username, $password) or die('Error to Connect');
mysql_select_db($db, $conn);
mysql_query('SET NAMES \'utf8\'');
mysql_set_charset('utf8');
$query = mysql_query("INSERT INTO `users` (id, name, family, father, username, password) VALUES (
'',
'$name',
'$family',
'$father',
'$user',
'$pass')");

header('Location: index.php');
exit();

// Select table
$result = mysql_query("SELECT * FROM `users`");
if ($result && mysql_num_rows($result) > 0) {
echo '<table width="100%" cellpadding="5px" cellspacing="0" border="1px">' . PHP_EOL;
echo '<tr><th>ID</th><th>Name</th><th>Family</th><th>Father</th><th>Username</th><th>Password</th></tr>';
while ($row = mysql_fetch_assoc($result)) {
echo '<tr>';
echo '<td>' . $row['id'] . '</td>';
echo '<td>' . $row['name'] . '</td>';
echo '<td>' . $row['family'] . '</td>';
echo '<td>' . $row['father'] . '</td>';
echo '<td>' . $row['username'] . '</td>';
echo '<td>' . $row['password'] . '</td>';
echo '</tr>' . PHP_EOL;
}
mysql_free_result($result);
echo '</table>' . PHP_EOL;
}
mysql_close($conn);
?>
</body>
</html>

کد صفحه index.php


<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title>صفحه اصلی</title>
<link rel="stylesheet" href="css/style.css" />
</head>
<body>
<div id="main">
<div class="sign">
<fieldset>
<table cellpadding="5px" cellspacing="0">
<form action="signup.php" method="post">
<legend>فرم عضویت</legend>
<tr><label for="name"> نام:<input type="text" name="name" placeholder="نام" /></label></tr><br />
<tr><label for="name"> نام خانوادگی:<input type="text" name="family" placeholder="نام خانوادگی" /></label></tr><br />
<tr><label for="name"> نام پدر:<input type="text" name="father" placeholder="نام پدر" /></label></tr><br />
<tr><label for="name"> نام کاربری:<input type="text" name="user" placeholder="نام کاربری" /></label></tr><br />
<tr><label for="name"> رمز عبور:<input type="password" name="pass" placeholder="رمز عبور" /></label></tr><br />
<tr><input type="submit" value="عضویت" /></tr>
<tr><input type="reset" value="اصلاح" /></tr>
</form>
</table>
<a href="login.php">ورود</a>
</fieldset>
</div>
</div>
</body>
</html>

ممنون

colors
جمعه 12 اردیبهشت 1393, 16:13 عصر
امنیت صفحه signup خیلی ضعفیه!

***BiDaK***
جمعه 12 اردیبهشت 1393, 16:32 عصر
اون قسمت شرط هاتو از or استفاده کن:


if (empty($name) || empty($family) || empty($father) || empty($user) || empty($pass))
{
header('Location: index.php');
exit();
}
بعد از کوئری insert اگه موفقیت آمیز بود:


if (mysql_affected_rows() > 0) {
header('Location: signup.php');
exit('<meta http-equiv="Refresh" content="0; url="signup.php">');
}
قسمت اینسرت رو توو یک شرط بذار که چک بشه اصلا ورودی پست شده یا نه اگه پست شده بود دستورات اینسرت اجرا بشن:


if (count($_POST) > 0) { // .... }
ورودی ها باید escape بشن. مثلا:


$name = mysql_real_escape_string($_POST['name']);

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

***BiDaK***
جمعه 12 اردیبهشت 1393, 16:46 عصر
محسن جان جلوی CSRF رو نمیگیره
اگه فرمی اکشنش get بود چی؟

meysam1366
جمعه 12 اردیبهشت 1393, 17:00 عصر
امنیت صفحه signup خیلی ضعفیه!

سلام

بله میدونم چون هنوز وارد مقوله امنیتش نشدم فعلا دارم چهار عمل اصلی CRUD رو یاد میگیرم

ممنون از راهنماییتون

meysam1366
جمعه 12 اردیبهشت 1393, 17:05 عصر
اون قسمت شرط هاتو از or استفاده کن:


if (empty($name) || empty($family) || empty($father) || empty($user) || empty($pass))
{
header('Location: index.php');
exit();
}
بعد از کوئری insert اگه موفقیت آمیز بود:


if (mysql_affected_rows() > 0) {
header('Location: signup.php');
exit('<meta http-equiv="Refresh" content="0; url="signup.php">');
}
قسمت اینسرت رو توو یک شرط بذار که چک بشه اصلا ورودی پست شده یا نه اگه پست شده بود دستورات اینسرت اجرا بشن:


if (count($_POST) > 0) { // .... }
ورودی ها باید escape بشن. مثلا:


$name = mysql_real_escape_string($_POST['name']);

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

سلام

ممنون از راهنماییتون

قسمت دوم رو توی شرط سوم بذارم؟

بله پکیج آقای شهرکی رو می بینم و مسائل امنیتیش رو هم میدونم بعدا قرارش میدم

ممنون

***BiDaK***
جمعه 12 اردیبهشت 1393, 17:07 عصر
کلا کدهای مربوط به اینسرت و mysql_affected_rows

meysam1366
جمعه 12 اردیبهشت 1393, 18:09 عصر
سلام

ببینید کدها رو درست نوشتم


<!DOCTYPE html>
<html>
<head>
<title>اطلاعات ثبت نام</title>
<meta charset="UTF-8" />
</head>
<body>
<?php
// اطلاعات ثبت نام
$id = '';
$name = $_POST['name'];
$family = $_POST['family'];
$father = $_POST['father'];
$user = $_POST['user'];
$pass = md5($_POST['pass']);

if (empty($name) || empty($family) || empty($father) || empty($user) || empty($pass)) {
header('Location: index.php');
exit();
}

// connet database & insert
$server = 'localhost';
$username = 'root';
$password = '';
$db = 'signup';
$conn = @mysql_connect($server, $username, $password) or die('Error to Connect');
mysql_select_db($db, $conn);
mysql_query('SET NAMES \'utf8\'');
mysql_set_charset('utf8');


if(count($_POST > 0)) {
$query = mysql_query("INSERT INTO `users` (id, name, family, father, username, password) VALUES (
'',
'$name',
'$family',
'$father',
'$user',
'$pass')");

if (mysql_affected_rows($query) > 0) {
header('Location: signup.php');
exit('<meta http-equiv="Refresh" content="0; url="signup.php">');
}

$result = mysql_query("SELECT * FROM `users`");
if ($result && mysql_num_rows($result) > 0) {
echo '<table width="100%" cellpadding="5px" cellspacing="0" border="1px">' . PHP_EOL;
echo '<tr><th>ID</th><th>Name</th><th>Family</th><th>Father</th><th>Username</th><th>Password</th></tr>';
while ($row = mysql_fetch_assoc($result)) {
echo '<tr>';
echo '<td>' . $row['id'] . '</td>';
echo '<td>' . $row['name'] . '</td>';
echo '<td>' . $row['family'] . '</td>';
echo '<td>' . $row['father'] . '</td>';
echo '<td>' . $row['username'] . '</td>';
echo '<td>' . $row['password'] . '</td>';
echo '</tr>' . PHP_EOL;
}
mysql_free_result($result);
echo '</table>' . PHP_EOL;
}
}

// Select table

mysql_close($conn);
?>
</body>
</html>

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

نمیدونم چیکار کنم گیج شدم

***BiDaK***
جمعه 12 اردیبهشت 1393, 18:21 عصر
mysql_affected_rows کوئری نمیگره.کانکشن میگیره.داخل پرانتزش رو خالی بگذار.
از result$ به بعد که مال سلکت به جدوله خارج از if اینسرت بگذار.(زیر کامنت سلکتت)
شرط رو هم درست بنویس: (0 < خارج از پرانتز count هست)

if(count($_POST) > 0)

meysam1366
جمعه 12 اردیبهشت 1393, 18:39 عصر
mysql_affected_rows کوئری نمیگره.کانکشن میگیره.داخل پرانتزش رو خالی بگذار.
از result$ به بعد که مال سلکت به جدوله خارج از if اینسرت بگذار.(زیر کامنت سلکتت)
شرط رو هم درست بنویس: (0 < خارج از پرانتز count هست)

if(count($_POST) > 0)

ممنون

این درسته؟


<!DOCTYPE html>
<html>
<head>
<title>اطلاعات ثبت نام</title>
<meta charset="UTF-8" />
</head>
<body>
<?php
// اطلاعات ثبت نام
$id = '';
$name = $_POST['name'];
$family = $_POST['family'];
$father = $_POST['father'];
$user = $_POST['user'];
$pass = md5($_POST['pass']);

if (empty($name) || empty($family) || empty($father) || empty($user) || empty($pass)) {
header('Location: index.php');
exit();
}

// connet database & insert
$server = 'localhost';
$username = 'root';
$password = '';
$db = 'signup';
$conn = @mysql_connect($server, $username, $password) or die('Error to Connect');
mysql_select_db($db, $conn);
mysql_query('SET NAMES \'utf8\'');
mysql_set_charset('utf8');


if(count($_POST) > 0) {
$query = mysql_query("INSERT INTO `users` (id, name, family, father, username, password) VALUES (
'',
'$name',
'$family',
'$father',
'$user',
'$pass')");

if (mysql_affected_rows() > 0) {
header('Location: signup.php');
exit('<meta http-equiv="Refresh" content="0; url="signup.php">');
}
}

// Select table
$result = mysql_query("SELECT * FROM `users`");
if ($result && mysql_num_rows($result) > 0) {
echo '<table width="100%" cellpadding="5px" cellspacing="0" border="1px">' . PHP_EOL;
echo '<tr><th>ID</th><th>Name</th><th>Family</th><th>Father</th><th>Username</th><th>Password</th></tr>';
while ($row = mysql_fetch_assoc($result)) {
echo '<tr>';
echo '<td>' . $row['id'] . '</td>';
echo '<td>' . $row['name'] . '</td>';
echo '<td>' . $row['family'] . '</td>';
echo '<td>' . $row['father'] . '</td>';
echo '<td>' . $row['username'] . '</td>';
echo '<td>' . $row['password'] . '</td>';
echo '</tr>' . PHP_EOL;
}
mysql_free_result($result);
echo '</table>' . PHP_EOL;
}
mysql_close($conn);
?>
</body>
</html>

درباره پسورد هش که گفتید


هش پسوردت خوب نیست.

یعنی چی؟

meysam1366
جمعه 12 اردیبهشت 1393, 18:41 عصر
mysql_affected_rows کوئری نمیگره.کانکشن میگیره.داخل پرانتزش رو خالی بگذار.
از result$ به بعد که مال سلکت به جدوله خارج از if اینسرت بگذار.(زیر کامنت سلکتت)
شرط رو هم درست بنویس: (0 < خارج از پرانتز count هست)

if(count($_POST) > 0)

ممنون

این درسته؟


<!DOCTYPE html>
<html>
<head>
<title>اطلاعات ثبت نام</title>
<meta charset="UTF-8" />
</head>
<body>
<?php
// اطلاعات ثبت نام
$id = '';
$name = $_POST['name'];
$family = $_POST['family'];
$father = $_POST['father'];
$user = $_POST['user'];
$pass = md5($_POST['pass']);

if (empty($name) || empty($family) || empty($father) || empty($user) || empty($pass)) {
header('Location: index.php');
exit();
}

// connet database & insert
$server = 'localhost';
$username = 'root';
$password = '';
$db = 'signup';
$conn = @mysql_connect($server, $username, $password) or die('Error to Connect');
mysql_select_db($db, $conn);
mysql_query('SET NAMES \'utf8\'');
mysql_set_charset('utf8');


if(count($_POST) > 0) {
$query = mysql_query("INSERT INTO `users` (id, name, family, father, username, password) VALUES (
'',
'$name',
'$family',
'$father',
'$user',
'$pass')");

if (mysql_affected_rows() > 0) {
header('Location: signup.php');
exit('<meta http-equiv="Refresh" content="0; url="signup.php">');
}
}

// Select table
$result = mysql_query("SELECT * FROM `users`");
if ($result && mysql_num_rows($result) > 0) {
echo '<table width="100%" cellpadding="5px" cellspacing="0" border="1px">' . PHP_EOL;
echo '<tr><th>ID</th><th>Name</th><th>Family</th><th>Father</th><th>Username</th><th>Password</th></tr>';
while ($row = mysql_fetch_assoc($result)) {
echo '<tr>';
echo '<td>' . $row['id'] . '</td>';
echo '<td>' . $row['name'] . '</td>';
echo '<td>' . $row['family'] . '</td>';
echo '<td>' . $row['father'] . '</td>';
echo '<td>' . $row['username'] . '</td>';
echo '<td>' . $row['password'] . '</td>';
echo '</tr>' . PHP_EOL;
}
mysql_free_result($result);
echo '</table>' . PHP_EOL;
}
mysql_close($conn);
?>
</body>
</html>

این کد رو تست کردم اصلا به صفحه signup.php نمیره و برمیگرده به صفحه index.php ولی اطلاعات توی دیتابیس ثبت میشه

درباره پسورد هش که گفتید


هش پسوردت خوب نیست.

یعنی چی؟

***BiDaK***
جمعه 12 اردیبهشت 1393, 18:52 عصر
این قسمت از کدت:


$name = $_POST['name'];
$family = $_POST['family'];
$father = $_POST['father'];
$user = $_POST['user'];
$pass = md5($_POST['pass']);

if (empty($name) || empty($family) || empty($father) || empty($user) || empty($pass)) {
header('Location: index.php');
exit();
}

باید در این if قرار بگیره:

if(count($_POST) > 0) {
دلیل اینکه میره به ایندکس واسه اینه که ائل که سابمیت میکنی کدها اجرا میشه و فیلد جدید اضافه میشه و شرط mysql_affected_rows اجرا میشه و صفحه دوبازه فراخوانی میشه و جون در فراخوانی مجدد اون کدهای بالات بیرون از if هستن مقداری دیگه ندارن و خالی هستن پس شرط اولی که گفتی اگه Empty هر کدومشون هدر به index اجرا بشه که هدر میشه.پس باید بیاریشون توی شرطی که مشخص کردم تا فقط زمانی که مقداری از فرم ارسال شده بود اجرا بشن.
واسه هش , جلسه ی 10 پکیج از روش salt , pepper استفاده شده.از همون استفاده کن.

meysam1366
جمعه 12 اردیبهشت 1393, 19:22 عصر
این قسمت از کدت:


$name = $_POST['name'];
$family = $_POST['family'];
$father = $_POST['father'];
$user = $_POST['user'];
$pass = md5($_POST['pass']);

if (empty($name) || empty($family) || empty($father) || empty($user) || empty($pass)) {
header('Location: index.php');
exit();
}

باید در این if قرار بگیره:

if(count($_POST) > 0) {
دلیل اینکه میره به ایندکس واسه اینه که ائل که سابمیت میکنی کدها اجرا میشه و فیلد جدید اضافه میشه و شرط mysql_affected_rows اجرا میشه و صفحه دوبازه فراخوانی میشه و جون در فراخوانی مجدد اون کدهای بالات بیرون از if هستن مقداری دیگه ندارن و خالی هستن پس شرط اولی که گفتی اگه Empty هر کدومشون هدر به index اجرا بشه که هدر میشه.پس باید بیاریشون توی شرطی که مشخص کردم تا فقط زمانی که مقداری از فرم ارسال شده بود اجرا بشن.
واسه هش , جلسه ی 10 پکیج از روش salt , pepper استفاده شده.از همون استفاده کن.

سلام

ممنون از شما دوست عزیز درست شد

خدا خیرتون بده

فقط یه سوال دیگه الان بخوام از ثبت نام اطلاعات تکراری جلوگیری کنم باید چیکار کنم اون رو باید با جی کوئری چک کنم یا با پی اچ پی هم میشه؟

مثلا نام کاربری تکراری دیگه ثبت نشه

barnamenevis1251
دوشنبه 27 مرداد 1393, 18:25 عصر
سلام
چند تا سؤال پیش میاد .
1- اینکه آیا قبلا مثلا یک یا چند فیلد خاص ثبت شده اند یا خیر ؟
2- آیا بعد از ثبت دوباره فرم با اطلاعات پر شده به کاربر نشان داده بشه یا خیر و اگر کاربر خواست یک فیلد را تغییر دهد چه بشود ( اگر نشان ندهیم و این همیشه یک دغدغه بوده ) ؟

من خودم این الگوریتم رو میپسندم :
1- قبل از ثبت اول با select ببینیم اطلاعات تو دیتابیس هست یا نه ( بر اساس یک یا چند فیلد کلیدی ) ؟
2- حالا اگه بود و دوباره ارسال شد آپدیت بشه لابد کاربر تصمیم به آپدیت مثلا نامش گرفته تا قبل از خروج از صفحه . البته آپدیت اگه تغییری در فیلد ها نباشه مقدار صفر بر میگردونه . یعنی انجام نمیشه .
3- حالا اگه مورد قبلا ثبت نشده بود تو دیتابیس ثبت بشه . و تمام .

فکر میکنم با این کار دیگه نیازی به header نباشه البته header نمیتونه جلوی ثبت مجدد رو بگیره .





//البته اینجا برای اتصال به پایگاه داده و درج از تابع استفاده شده که نیاز به توضیح بیشتر ندیدم و بیشتر منظور تابع درج بود .
// در ضمن موارد امنیتی هم رعایت شده است .
function __construct()
{

$db_connection = new dbConnection();
$this->link=$db_connection->connect();
return $this->link;

}

function sabtnam($fname,$lname,$melli,$email)
{

$query=$this->link->prepare("SELECT * FROM `kke_family` WHERE `melli`=? ");
$values=array($melli);
$query->execute($values);
$counts=$query->rowCount();

if($counts==0)
{$query = $this->link->prepare("INSERT INTO `kke_family` (`fname`,`lname`,`melli`,`email` ) VALUES (?,?,?,?)");
$values=array($fname,$lname,$melli,$email);
$query->execute($values);
$counts=$query->rowCount();
return $counts ;}
elseif($counts>0)
{
// در صورت وجود کد ملی آپدیت شود
$query=$this->link->prepare("UPDATE `kke_family` SET `fname`=?,`lname`=?,`email`=? WHERE `melli`=? ");// اگر where مشخص نشود تمام ردیف ها به این مشخصات تغییر می کند .
$values=array($fname,$lname,$email,$melli);// $melli را آخر می نویسیم
$query->execute($values);
$counts=$query->rowCount();
return $counts ;
} // BY melli
else
{return 0 ;}


}




البته اگر کاستی یا ایرادی وجود دارد دوستان تکمیل بفرمایند . با تشکر