ฉันต้องการสร้างสตริงอักขระแบบสุ่ม 5 ตัวที่มีโอกาสซ้ำกันน้อยที่สุด วิธีที่ดีที่สุดจะทำอย่างไร? ขอบคุณ.
Random::alphanumericString($length)
คุณสามารถรับสตริงที่มี 0-9a-zA-Z ที่มาจากข้อมูลสุ่มที่ปลอดภัยด้วยการเข้ารหัส
ฉันต้องการสร้างสตริงอักขระแบบสุ่ม 5 ตัวที่มีโอกาสซ้ำกันน้อยที่สุด วิธีที่ดีที่สุดจะทำอย่างไร? ขอบคุณ.
Random::alphanumericString($length)
คุณสามารถรับสตริงที่มี 0-9a-zA-Z ที่มาจากข้อมูลสุ่มที่ปลอดภัยด้วยการเข้ารหัส
คำตอบ:
$rand = substr(md5(microtime()),rand(0,26),5);
จะเป็นการเดาที่ดีที่สุดของฉัน - เว้นแต่คุณจะมองหาตัวละครพิเศษด้วย:
$seed = str_split('abcdefghijklmnopqrstuvwxyz'
.'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
.'0123456789!@#$%^&*()'); // and any other characters
shuffle($seed); // probably optional since array_is randomized; this may be redundant
$rand = '';
foreach (array_rand($seed, 5) as $k) $rand .= $seed[$k];
และสำหรับนาฬิกาตามนาฬิกา (การชนน้อยลงเนื่องจากเป็นการเพิ่มขึ้น):
function incrementalHash($len = 5){
$charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
$base = strlen($charset);
$result = '';
$now = explode(' ', microtime())[1];
while ($now >= $base){
$i = $now % $base;
$result = $charset[$i] . $result;
$now /= $base;
}
return substr($result, -5);
}
หมายเหตุ: การเพิ่มขึ้นหมายถึงง่ายต่อการคาดเดา หากคุณกำลังใช้สิ่งนี้เป็นเกลือหรือโทเค็นการยืนยันอย่าทำ เกลือ (ตอนนี้) ของ "WCWyb" หมายถึง 5 วินาทีนับจากนี้คือ "WCWyg")
md5()
คือคุณได้รับสตริงที่ประกอบด้วยชุดอักขระ 16 ตัว (10 หลักและa
ถึงf
คือ 4 บิตต่ออักขระสตริง) สิ่งนี้อาจเพียงพอสำหรับวัตถุประสงค์บางอย่าง แต่อาจน้อยเกินไปสำหรับวัตถุประสงค์ในการเข้ารหัส (อักขระห้าตัวจาก 16 สัญลักษณ์ = 16 ^ 5 = 20 บิต = ความเป็นไปได้ 1048576)
array_rand($seed, 5)
จะส่งคืนคีย์อาร์เรย์ไม่ใช่ค่าดังนั้นรหัสของคุณจะไม่ทำงาน
"
, '
และทับขวาใน$charset
? ฉันจำเป็นต้องใช้ลำดับการหลีกเพื่อรวมอักขระเหล่านั้นหรือไม่
$len
พารามิเตอร์อินพุตด้วยซ้ำ... คุณลืมมันไปหรือเปล่า?
หากfor
ลูปขาดตลาดนี่คือสิ่งที่ฉันชอบใช้:
$s = substr(str_shuffle(str_repeat("0123456789abcdefghijklmnopqrstuvwxyz", 5)), 0, 5);
str_shuffle('ab')
จะให้ab
หรือแต่ไม่เคยba
aa
การเพิ่มการstr_repeat
อนุญาตสำหรับสิ่งนั้น แต่ที่กล่าวว่าวิธีแก้ปัญหาที่ฉันให้นั้นไม่ได้ร้ายแรงจริงๆ ... แม้ว่ามันจะได้ผล
l
, i
, 1
, 0
, O
ฯลฯ และจาก 500 คูปองได้ไม่ซ้ำกัน
วิธีที่รวดเร็วคือการใช้อักขระที่ผันผวนที่สุดของฟังก์ชันuniqid
ตัวอย่างเช่น:
$rand = substr(uniqid('', true), -5);
คุณสามารถลองทำได้ง่ายๆดังนี้:
$length = 5;
$randomletter = substr(str_shuffle("abcdefghijklmnopqrstuvwxyz"), 0, $length);
รายละเอียดเพิ่มเติม: http://forum.arnlweb.com/viewtopic.php?f=7&t=25
สิ่งต่อไปนี้ควรให้โอกาสในการทำซ้ำน้อยที่สุด (คุณอาจต้องการแทนที่mt_rand()
ด้วยแหล่งที่มาของตัวเลขสุ่มที่ดีกว่าเช่นจาก/dev/*random
หรือจาก GUID):
<?php
$characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
$result = '';
for ($i = 0; $i < 5; $i++)
$result .= $characters[mt_rand(0, 61)];
?>
แก้ไข:
หากคุณมีความกังวลเกี่ยวกับความปลอดภัยจริงๆไม่ได้ใช้rand()
หรือmt_rand()
และตรวจสอบว่าอุปกรณ์ข้อมูลแบบสุ่มของคุณเป็นจริงอุปกรณ์สร้างแบบสุ่ม/dev/zero
ข้อมูลที่ไม่ได้เป็นแฟ้มปกติหรือสิ่งที่คาดเดาได้เช่น mt_rand()
ถือว่าเป็นอันตราย:
https://spideroak.com/blog/20121205114003-exploit-information-leaks-in-random-numbers-from-python-ruby-and-php
แก้ไข:
หากคุณรองรับ OpenSSL ใน PHP คุณสามารถใช้openssl_random_pseudo_bytes()
:
<?php
$length = 5;
$randomBytes = openssl_random_pseudo_bytes($length);
$characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
$charactersLength = strlen($characters);
$result = '';
for ($i = 0; $i < $length; $i++)
$result .= $characters[ord($randomBytes[$i]) % $charactersLength];
?>
strlen()
แบบวนซ้ำเป็นค่าใช้จ่ายที่ไม่จำเป็นโดยเฉพาะอย่างยิ่งถ้าคุณรู้อยู่แล้วว่าชุดอักขระจะไม่เปลี่ยนแปลงในระหว่างนี้
ฉันมักจะใช้ฟังก์ชันเดียวกันสำหรับสิ่งนี้โดยปกติจะสร้างรหัสผ่าน ใช้งานง่ายและมีประโยชน์
function randPass($length, $strength=8) {
$vowels = 'aeuy';
$consonants = 'bdghjmnpqrstvz';
if ($strength >= 1) {
$consonants .= 'BDGHJLMNPQRSTVWXZ';
}
if ($strength >= 2) {
$vowels .= "AEUY";
}
if ($strength >= 4) {
$consonants .= '23456789';
}
if ($strength >= 8) {
$consonants .= '@#$%';
}
$password = '';
$alt = time() % 2;
for ($i = 0; $i < $length; $i++) {
if ($alt == 1) {
$password .= $consonants[(rand() % strlen($consonants))];
$alt = 0;
} else {
$password .= $vowels[(rand() % strlen($vowels))];
$alt = 1;
}
}
return $password;
}
ดูเหมือนว่าstr_shuffleจะเป็นประโยชน์สำหรับสิ่งนี้ เริ่มต้นการสุ่มด้วยอักขระใดก็ได้ที่คุณต้องการ
$my_rand_strng = substr(str_shuffle("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), -5);
$str = '';
$str_len = 8;
for($i = 0, $i < $str_len; $i++){
//97 is ascii code for 'a' and 122 is ascii code for z
$str .= chr(rand(97, 122));
}
return $str
หากเป็นไปได้ว่าคุณจะได้รับเฉพาะ AF ตัวอักษรนี่คือวิธีแก้ปัญหาของฉัน:
str_pad(dechex(mt_rand(0, 0xFFFFF)), 5, '0', STR_PAD_LEFT);
ฉันเชื่อว่าการใช้ฟังก์ชันแฮชเป็นการใช้งานมากเกินไปสำหรับงานง่ายๆเช่นการสร้างลำดับเลขฐานสิบหกแบบสุ่ม dechex
+ mt_rand
จะทำงานเดียวกัน แต่ไม่มีงานเข้ารหัสที่ไม่จำเป็น str_pad
รับประกันความยาว 5 อักขระของสตริงเอาต์พุต (หากตัวเลขสุ่มน้อยกว่า 0x10000)
ความน่าจะเป็นที่ซ้ำกันขึ้นอยู่กับmt_rand
ความน่าเชื่อถือของ Mersenne Twister ขึ้นชื่อเรื่องการสุ่มคุณภาพสูงดังนั้นจึงควรเข้ากับงานได้ดี
ฉันยังไม่ทราบวิธีการทำเช่นนี้จนผมคิดว่าการใช้ PHP array
's และฉันค่อนข้างมั่นใจว่านี่เป็นวิธีที่ง่ายที่สุดในการสร้างสตริงหรือตัวเลขสุ่มด้วยอาร์เรย์ รหัส:
function randstr ($len=10, $abc="aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789") {
$letters = str_split($abc);
$str = "";
for ($i=0; $i<=$len; $i++) {
$str .= $letters[rand(0, count($letters)-1)];
};
return $str;
};
คุณสามารถใช้ฟังก์ชันนี้ได้เช่นนี้
randstr(20) // returns a random 20 letter string
// Or like this
randstr(5, abc) // returns a random 5 letter string using the letters "abc"
คล้ายกับBrad Christieคำตอบของแต่ใช้sha1
alrorithm สำหรับอักขระ0-9a-zA-Z
และนำหน้าด้วยค่าสุ่ม:
$str = substr(sha1(mt_rand() . microtime()), mt_rand(0,35), 5);
แต่ถ้าคุณตั้งค่าอักขระที่กำหนด (อนุญาต):
$validChars = array('0','1','2' /*...*/,'?','-','_','a','b','c' /*...*/);
$validCharsCount = count($validChars);
$str = '';
for ($i=0; $i<5; $i++) {
$str .= $validChars[rand(0,$validCharsCount - 1)];
}
** อัพเดท **
ตามที่Archimedixชี้ให้เห็นสิ่งนี้จะไม่รับประกันว่าจะส่งคืน "ความเป็นไปได้น้อยที่สุดในการทำซ้ำ" เนื่องจากจำนวนชุดค่าผสมต่ำสำหรับช่วงอักขระที่กำหนด คุณจะต้องเพิ่มจำนวนอักขระหรืออนุญาตให้มีอักขระพิเศษ (พิเศษ) ในสตริง ทางออกแรกน่าจะดีกว่าในกรณีของคุณ
time()
เป็นถึง 1 microtime()
ล้านครั้งคาดการณ์มากขึ้นกว่า
$str
รูปแบบสำหรับ
˫§»⁋⅓
" เพียงเพราะปลอดภัยกว่า ... คุณเพิ่มคีย์อ้างอิงเป็น 7 อักขระขึ้นไป . (BTW: การแก้ไขในความคิดเห็นก่อนหน้าของฉันมันคือ 5x36 ตัวอักษร)
ทำงานได้ดีในPHP (php 5.4.4)
$seed = str_split('abcdefghijklmnopqrstuvwxyz');
$rand = array_rand($seed, 5);
$convert = array_map(function($n){
global $seed;
return $seed[$n];
},$rand);
$var = implode('',$convert);
echo $var;
ที่มา: ฟังก์ชัน PHP ที่สร้างอักขระสุ่ม
ฟังก์ชัน PHP ง่ายๆนี้ใช้ได้กับฉัน:
function cvf_ps_generate_random_code($length=10) {
$string = '';
// You can define your own characters here.
$characters = "23456789ABCDEFHJKLMNPRTVWXYZabcdefghijklmnopqrstuvwxyz";
for ($p = 0; $p < $length; $p++) {
$string .= $characters[mt_rand(0, strlen($characters)-1)];
}
return $string;
}
การใช้งาน:
echo cvf_ps_generate_random_code(5);
นี่คือrandom 5 cents
...
$random=function($a, $b) {
return(
substr(str_shuffle(('\\`)/|@'.
password_hash(mt_rand(0,999999),
PASSWORD_DEFAULT).'!*^&~(')),
$a, $b)
);
};
echo($random(0,5));
ใหม่ของ PHP password_hash()
ฟังก์ชัน (*> = PHP 5.5) ของ PHP กำลังทำงานในการสร้างชุดอักขระตัวพิมพ์ใหญ่และตัวพิมพ์เล็กและตัวเลขที่ยาวพอสมควร
สองข้อต่อ สตริงก่อนและหลังpassword_hash
ภายในฟังก์ชันสุ่ม $ เหมาะสำหรับการเปลี่ยนแปลง
พารามิเตอร์สำหรับ$random()
* ($ a, $ b) เป็นsubstr()
พารามิเตอร์จริงๆ :)
หมายเหตุ:สิ่งนี้ไม่จำเป็นต้องเป็นฟังก์ชัน แต่ก็สามารถเป็นตัวแปรปกติได้เช่นกัน .. เป็น singleliner ที่น่ารังเกียจเช่นนี้:
$random=(substr(str_shuffle(('\\`)/|@'.password_hash(mt_rand(0,999999), PASSWORD_DEFAULT).'!*^&~(')), 0, 5));
echo($random);
function CaracteresAleatorios( $Tamanno, $Opciones) {
$Opciones = empty($Opciones) ? array(0, 1, 2) : $Opciones;
$Tamanno = empty($Tamanno) ? 16 : $Tamanno;
$Caracteres=array("0123456789","abcdefghijklmnopqrstuvwxyz","ABCDEFGHIJKLMNOPQRSTUVWXYZ");
$Caracteres= implode("",array_intersect_key($Caracteres, array_flip($Opciones)));
$CantidadCaracteres=strlen($Caracteres)-1;
$CaracteresAleatorios='';
for ($k = 0; $k < $Tamanno; $k++) {
$CaracteresAleatorios.=$Caracteres[rand(0, $CantidadCaracteres)];
}
return $CaracteresAleatorios;
}
ฉันไม่เคยใช้สิ่งนี้:
<?php function fRand($len) {
$str = '';
$a = "abcdefghijklmnopqrstuvwxyz0123456789";
$b = str_split($a);
for ($i=1; $i <= $len ; $i++) {
$str .= $b[rand(0,strlen($a)-1)];
}
return $str;
} ?>
เมื่อคุณเรียกมันให้ตั้งค่าความยาวของสตริง
<?php echo fRand([LENGHT]); ?>
$a
นอกจากนี้คุณยังสามารถเปลี่ยนตัวละครที่เป็นไปได้ในสตริง
0-9a-zA-Z
?