PDA

View Full Version : سوال: سوال: چگونه یک عدد راندوم به عنوان آی_دی کاربر بسازیم؟



rezaeirezaei48
چهارشنبه 01 مرداد 1393, 02:00 صبح
فرض کنید می خوایم یه عدد راندوم رو به عنوان کلید اصلی تو جدول کاربران ثبت کنیم

باید این عدد کاملا unique باشه، و فرض می کنیم تعداد ثبت نام کاربر بالا هست به طوری که احتمال اینکه چندکاربر در هر ثانیه همزمان ثبت نام کنن زیاد باشه و در حد 100 درصد. پس نمیشه از timestamp استفاده کرد.

یه جا ایده ی خودم این بود که از اونجایی که ایمیل کاربران هم یکتاست، کد حروف رو بذارم، اما ممکنه ایمیل یه نفر زیاد باشه و از حد تجاوز کنه فرض کنید 14 یا حداکثر 17 عدد می خوایم که در این صورت باز هم تداخل وجود داره. اگه بخوایم 17 حرف اول رو برداریم. (ممکنه 17 حرف اول دوتا ایمیل عینا یکی باشن) برای مثال:

rezaeirezaei48@example.com و rezaeirezaei49@example.com

یا کلا حروف ایمیل به حد نصاب نرسه مثل: rezaei@abc.ir

به نظرتون راه حل ساخت یه عدد یکتای تصادفی با تعداد رقم معلوم چیه که نزدیکترین شباهت رو به یه عدد تصادفی واقعی داشته باشه؟

ashokri.nll
چهارشنبه 01 مرداد 1393, 02:35 صبح
دوست عزیز دیتابیس این امکان رو میده .
اگه از mysql استفاده می کنید در نمای تصویری هر ستون رو میخاید تیک AI رو فعال کنید عدد unique بهتون میده ولی پشت سرهم یعنی از 1 شروع میشه تا N .

mfaridi
چهارشنبه 01 مرداد 1393, 04:04 صبح
از این استفاده کن شاید به کارت بیاد
create table db_user( id int AUTO_INCREMENT PRIMARY KEY,
user varchar (20),
pass varchar (32),
mail varchar (99)
)

rezaeirezaei48
چهارشنبه 01 مرداد 1393, 14:14 عصر
دوست عزیز دیتابیس این امکان رو میده .
اگه از mysql استفاده می کنید در نمای تصویری هر ستون رو میخاید تیک AI رو فعال کنید عدد unique بهتون میده ولی پشت سرهم یعنی از 1 شروع میشه تا N .

اینو می دونم، اینجوری مشکلاتی به وجود میاره



از این استفاده کن شاید به کارت بیاد
create table db_user( id int AUTO_INCREMENT PRIMARY KEY,
user varchar (20),
pass varchar (32),
mail varchar (99)
)

همون جواب بود متاسفانه

--------------------------

درسته دنبال یه ID کاملا یکتا برای کاربران می گردم اما نمی خوام این عدد یا رشته ای از اعداد توسط دیتابیس ایجاد بشه.

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

کسی خبر نداره فیسبوک یا تویتر از چه الگوریتمی استفاده می کنند؟

farzadyazdan
چهارشنبه 01 مرداد 1393, 14:24 عصر
فکر میکنم اگر از تابع uniqid استفاده کنید به نتیجه مورد نظرتون برسید

http://php.net/manual/en/function.uniqid.php

rezaeirezaei48
چهارشنبه 01 مرداد 1393, 14:36 عصر
فکر میکنم اگر از تابع uniqid استفاده کنید به نتیجه مورد نظرتون برسید

http://php.net/manual/en/function.uniqid.php

uniqid تابع مورد نظر من نیست. در بهترین حالت 23 کاراکتر عددی و حروف رو می سازه که نمونه هاش شباهت زیادی با هم دارند و اگه بخوای درصد شباهتشون رو به دست بیاری با خود توابع پی اچ پی درصد بالایی رو نشون میده (با similar_text) امتحان کن.


درضمن من عدد می خوام و یه چیز دیگه که در مورد این تابع یادمه اینه که خود پی اچ پی گفته برای موارد امنیتی استفاده نکنید!

farzadyazdan
چهارشنبه 01 مرداد 1393, 14:46 عصر
میشه دلیلتون برای عدم استفاده از AI خود my sql رو بگین
ممنون

rezaeirezaei48
چهارشنبه 01 مرداد 1393, 14:55 عصر
میشه دلیلتون برای عدم استفاده از AI خود my sql رو بگین
ممنون

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

اما اگه دستور خاصی نداشته باشه حداقلش حدس زدن آی دی ها خیلی سخت میشه و ضمنا تعداد کاربران تنها برای مدیرای سایت معلومه.

و یه چیز دیگه اینکه فک کن عدد خیلی بزرگ باشه و بخوای به صورت عدد باهاش برخورد کنی و مثلا تو یه بازه رو چندتا کاربر نشون بدی، کافیه یه عدد رو بهش اضافه یا کم کنی ...


و خیلی دلایل دیگه که اصلی ترینش کاستومایزه

کلا من دنبال یه الگوریتم ساخت عدد یکتا هستم و نمی خوام سر خودمو کلاه بذارم و دور بزنم سوال رو

farzadyazdan
چهارشنبه 01 مرداد 1393, 15:23 عصر
اینجوری اولا نمیتونم عددی رو که به عنوان شناسه یکتای کاربر درنظر می گیرم رو کاستوم کنم، ثانیا کافیه یه باگ پیدا بشه اونوقت یه نفر خیلی راحت می تونه تمام اطلاعات رو با اضافه یا کم کردن یه آی دی بدزده.

اما اگه دستور خاصی نداشته باشه حداقلش حدس زدن آی دی ها خیلی سخت میشه و ضمنا تعداد کاربران تنها برای مدیرای سایت معلومه.

و یه چیز دیگه اینکه فک کن عدد خیلی بزرگ باشه و بخوای به صورت عدد باهاش برخورد کنی و مثلا تو یه بازه رو چندتا کاربر نشون بدی، کافیه یه عدد رو بهش اضافه یا کم کنی ...


و خیلی دلایل دیگه که اصلی ترینش کاستومایزه

کلا من دنبال یه الگوریتم ساخت عدد یکتا هستم و نمی خوام سر خودمو کلاه بذارم و دور بزنم سوال رو

فکر خیلی خوبی
البته من در یکی از پروژه هام به یک روش دیگه عمل کردم
- وقتی که یک رکورد رو از دیتابیس میگرفتم id اون رکورد رو code میکردم و وقتی که میخواستم اطلاعاتی راجع به اون رکورد بدست بیارم اطلاعات رو اول decode میکردم و بعد به دیتابیس میفرستادم

بنظرتون این روش روش خوبی هست یا نه؟

rezaeirezaei48
چهارشنبه 01 مرداد 1393, 15:33 عصر
به نظرم کار اضافی هست اگه آی دی رو به صورت عمومی در اختیار کاربر قرار بدید.

فرض کنیم آی دی این باشه
http://www.example.com/user.php?id=456321

وقتی دیکد و انکد باشه بازم فرقی نداره وقتی یه نفر اون یک رو به دو تغییر بده باز هم اطلاعات کاربر رو نشون میده!

یادمه تو گوگل پلاس یه اکانت داشتم حذفش کردم تمام اطلاعات رو از بین بردم اما یه سایت که تمام اطلاعات گوگل پلاس رو دزدیده بود اطلاعات من رو داشت، الان هر موقع جستوجو می کنم تمام اطلاعاتم رو که به صورت پابلیک بودن نشون میده.اشتباهشون علاوه بر روش غلط گوگل برای یکتا کردن کاربرا این بود که این کارو نکردن: اگه یه آی پی در کمتر از (مثلا) 5 ثانیه به 100 اکانت سر زدن یه کد کپچا نشونش بده. چون احتمال اینکه ربات باشه در حد 100 درصده!

arenaw
چهارشنبه 01 مرداد 1393, 15:52 عصر
مثلا میتونی آیدی رو از همون اوتو اینکرامنت مای اس کیو ال استفاده کنی + یه فیلد دیگه که هش شده ی همون آیدیه. زمانی که میخوای ازش استفاده کنی، از اون هش شده هه استفاده کن.
هش شده ی 1 (ام دی فایو) میشه : c4ca4238a0b923820dcc509a6f75849b
و هش شده ی 2 میشه : c81e728d9d4c2f636f067f89cc14862c
که تقریبا مشکل شمارو حل میکنه

rezaeirezaei48
چهارشنبه 01 مرداد 1393, 16:41 عصر
مثلا میتونی آیدی رو از همون اوتو اینکرامنت مای اس کیو ال استفاده کنی + یه فیلد دیگه که هش شده ی همون آیدیه. زمانی که میخوای ازش استفاده کنی، از اون هش شده هه استفاده کن.
هش شده ی 1 (ام دی فایو) میشه : c4ca4238a0b923820dcc509a6f75849b
و هش شده ی 2 میشه : c81e728d9d4c2f636f067f89cc14862c
که تقریبا مشکل شمارو حل میکنه

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

Unique
چهارشنبه 01 مرداد 1393, 17:18 عصر
اینجوری اولا نمیتونم عددی رو که به عنوان شناسه یکتای کاربر درنظر می گیرم رو کاستوم کنم، ثانیا کافیه یه باگ پیدا بشه اونوقت یه نفر خیلی راحت می تونه تمام اطلاعات رو با اضافه یا کم کردن یه آی دی بدزده.

چون id باید یکت اباشه پس کلا چیزی به نام customize معنی پیدا نمیکنه ! شما چی را میخواین customize کنین ؟ در مورد باگ هم اصلا دونستن id رکورد ها هیچ مشکل امنیتی به وجود نمیاره !
اصلا این جدول شما چی هست ؟‌جدول user ها هستش ؟

در مورد تعداد کاربران هم اولا که اصلا مهم نیست و اگه هم مهم باشه شما بیا هر id را با یک عدد مثل ۵۶۸۹۷۸۷۸۴۵ جمع کن و توی url ها بگذار.

بهترین راه برای یکتا بودن استفاده از auto inc هست چون نه دیگه table lock نیازه و نه چک کردن و این حرفا داره. به نظر من هیچ دلیلی برای عدم استفاده از auto inc وجود نداره ،‌ من یک زمانی از GUID استفاده میکردم ولی اون هم به درد نمیخور ، حتی میشه timestamp را بر حسب میلی ثانیه به دست آورد که خودش خیلی unique هست ! ولی فرق bigint و int و mediumint تی تعداد فیلد بالا و index توی همین ۴ یا ۵ بایت کم و زیاد به قدر یتوی Performance تاثیر داره که دیوونگیه شما چنین ارقام بزرگی بخواین استفاده کنین.

تا دلیل درست و حسابی نباشه کار بی معنی هستش و من تا حالا هیچ دلیلی برای این کار پیدا نکردم و دوست دارم وقعا بدونم چرا شما نمیخواین استفاده کنین ؟

rezaeirezaei48
چهارشنبه 01 مرداد 1393, 17:36 عصر
دوست عزیز AI و جدول رو بیخیال شو من دنبال یه الگوریتم هستم برای ساخت یه عدد یکتا، اگه بخوام از timestamp استفاده کنم که ممکنه چندکاربر دقیقا تو یه ثانیه به دیتابیس وصل بشن
AI هم اگه استفاده کنم که دیگه نمیشه تغییرش داد و ضربو اینکار ها رو انجام داد.

وقتی فیلد رو اتومات باشه که دیگه نمیشه توش چیزی نوشت یا میشه من نمی دونم اگه بشه واقعا مشکلم حل میشه! درضمن این فیلد کلید اصلی هستش و برای جداول دیگه خارجی.
اگه بشه تو فیلد نوشت بعد دیتابیس بهش عدد اضافه کنه که دیگه مشکلی نیست. یه عدد رندم میذاریم توش دیتابیس خودش کارارو انجام میده. به همین سادگی


کلا من دنبال یه الگوریتم هستم شما جداول رو بیخیال شو، دنبال یه الگوریتم که یه رشته عددی یکتا و تصادفی بسازه دیگه ذهنتو درگیر بقیش نکن

Veteran
چهارشنبه 01 مرداد 1393, 17:51 عصر
()Microtime

rezaeirezaei48
چهارشنبه 01 مرداد 1393, 17:58 عصر
()Microtime

الان دارم از همین استفاده می کنم. ولی شک دارم درست باشه و اینکه همیشه یک عدد 18 رقمی رو برگشت بده

یه شرط براش گذاشتم بعد از تریم کردن کاراکترهای اضافی اگه عدد 18ررقم بود اضافه کن اگه نه بیخیالش. به نظرت درسته؟

rezaeirezaei48
چهارشنبه 01 مرداد 1393, 18:19 عصر
Veteran (http://barnamenevis.org/member.php?160830-Veteran) ممنونم، اصلا به میکرو فک نکرده بودم حالا با این کد فک کنم مشکلی نباشه، اما از اونجایی که بازم احتمال هست باید یه چک تو دیتابیس بکنیم (این مشکل بزرگیه :ناراحت:) ولی خب احتمالش خیلی کمه که دو کاربر تو یه ثانیه یک میلی ثانیه و دقییقا یک میکرو ثانیه با هم درخواست بفرستن درسته؟



usleep(rand(1000,9999);
microtime();

rezaeirezaei48
چهارشنبه 01 مرداد 1393, 18:34 عصر
یه مشکل دیگه اینکه همیشه تعداد آی دی ها یکی نیست از این کد استفاده کردم:


for ($i = 0;$i<10;$i++) {

usleep ($n = mt_rand(1000,9999));

$m = microtime(true);
$x = explode('.',$m);

$id = $x[0].$x[1];

echo 'id: '.$id . '<br>length:'.strlen($id).'<br>rand num: '.$n.'<br><hr>';
}

که نتیجه زیر رو داد:

id: 14061260314576
length:14
rand num: 9965
id: 14061260314732
length:14
rand num: 5561
id: 14061260314888
length:14
rand num: 4837
id: 14061260315044
length:14
rand num: 1512
id: 140612603152
length:12
rand num: 9495
id: 14061260315356
length:14
rand num: 4536
id: 14061260315512
length:14
rand num: 4661
id: 14061260315668
length:14
rand num: 1682
id: 14061260315824
length:14
rand num: 8980
id: 1406126031598
length:13
rand num: 5053

Veteran
چهارشنبه 01 مرداد 1393, 19:51 عصر
<?php
/**
* Class to generate random unique string and/or numbers.
*
* @author Rochak Chauhan <rochakchauhan@gmail.com>
*/
class PhpRandomNumberGenerator {

private $charLimit = 8;
private $charArray = array();

function generateNumber() {
$bits = $this->charLimit * 5;
$nos = (int) $bits / 25;
$random = "";
for ($i = 0; $i <= $nos; $i++) {
$random.=$this->getRandomBinaryNumbers();
}
$random = chunk_split($random, 5, "#*#");
//Set default char set
if (count($this->charArray) < (($this->charLimit)*2) ) {
$this->setDefaultCharArray();
}
$number = "";
$tmpArray = explode("#*#", $random);
foreach ($tmpArray as $ref => $b) {
$b = bindec($b);
$b = (int) $b;
if ($b >= 0) {
$c = $this->charArray[$b];
$number.= $c;
}
}
$strlen = strlen($number);
$diff = $strlen - $this->charLimit;
if ($diff < 0) {
$diff = abs($diff);
$pre = "";
for ($i = 0; $i < $diff; $i++) {
$pre.="0";
}
$number = $pre . $number;
}
$number = substr($number, 0, $this->charLimit);
return $number;
}

/**
* Function to set Default Char Array
*/
private function setDefaultCharArray() {
$numbersArray = $this->generateNumbersArray();
$this->charArray = array_merge($this->charArray, $numbersArray);
$upperCaseArray = $this->generateUpperCaseArray();
$this->charArray = array_merge($this->charArray, $upperCaseArray);
$lowerCaseArray = $this->generateLowerCaseArray();
$this->charArray = array_merge($this->charArray, $lowerCaseArray);
}

/**
* Function to generate lowercase alphbets array
*
* @return array
*/
private function generateLowerCaseArray() {
$return = array();
for ($i = 97; $i <= 122; $i++) {
$return[] = chr($i);
}
return $return;
}

/**
* Function to generate uppercase alphbets array
*
* @return array
*/
private function generateUpperCaseArray() {
$return = array();
for ($i = 65; $i <= 90; $i++) {
$return[] = chr($i);
}
return $return;
}

/**
* Function to generate Numbers array
*
* @return array
*/
private function generateNumbersArray() {
$return = array();
for ($i = 48; $i <= 57; $i++) {
$return[] = chr($i);
}
return $return;
}

/**
* Function to Generate Randaom Binary Numbers (between 25-30 chars)
*
* @return string
*/
private function getRandomBinaryNumbers() {
$rand = mt_rand();
return decbin($rand);
}

/**
* Function to set Char Limit
*
* @param int $char_limit
* @return void
*/
function setCharLimit($char_limit) {
$this->charLimit = $char_limit;
}

/**
* Function to set CharArray
*
* @param int $charArray
* @return void
*/
function setType($charArray) {
$this->charArray = array_merge($this->charArray, $charArray);
}

}

?>



<?php
require("PhpRandomNumberGenerator.inc.php");
$obj=new PhpRandomNumberGenerator();

$num=$obj->generateNumber();

echo "<h2>$num</h2>";
?>

Unique
چهارشنبه 01 مرداد 1393, 21:02 عصر
کلا من دنبال یه الگوریتم هستم شما جداول رو بیخیال شو، دنبال یه الگوریتم که یه رشته عددی یکتا و تصادفی بسازه دیگه ذهنتو درگیر بقیش نکن

اینو از من کوچیک داشته باش که همیشه اون طرح و روالی که توی ذهن ما هستش جواب و راه حل کامل و درست نیست !

شما چی را با چی میخوای ضرب کنی ؟ اصلا گیریم شما یک عدد رندوم درست کردی که یکتا بودش خوب حالا چی ؟ چطور عددی که اصلا نمیدونی چی میخواد بشه را میتوی customize کنی ولی AI نمیشه ؟ در ضمن کی گفته نمیشه فیلد AI را را تغییر داد !؟ میتونی از AI خارجش کنی و تغییراتت را بدی و دوباره AI کنی. البته این کار درستی نیست ! اگه index داشته باشی و relation تعریف کرده باشی و این حرفا این کار ها روی کلید اصلی که توی جداول دیگه خارجی هست هم زمان بره و هم مشکل ساز. ای کاش به جای اینکه میگفتی به صورت پیش فرض بی خیال AI ، میگفتی چرا AI براتون جواب نمیده. شاید تجربه دوستان به کار شما بیاد. شما با همون Microtime و قفل کردن جدول به راحتی میتونی کارت را انجام بدی و duplicate نخواهی داشت ولی به نظر من که اصلا اصولی نیست.

rezaeirezaei48
چهارشنبه 01 مرداد 1393, 21:33 عصر
شما با همون Microtime و قفل کردن جدول به راحتی میتونی کارت را انجام بدی و duplicate نخواهی داشت ولی به نظر من که اصلا اصولی نیست.

ممنونم از اینکه دلسوزانه جواب می دی

به نظرت چیکار کنم که یه آی دی 14 رقمی یا بیشتر داشته باشم حالا به هر روشی

Unique
چهارشنبه 01 مرداد 1393, 22:54 عصر
من نظرم را گفتم دوست من ، AI بهترین روش هست و نمیتونم روشی را پیشنهاد بدم یا توضیح بدم که اصلا منطقی نیست.

موفق باشی