Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> [PHP/MySQL] Generowanie kodów dostępu
starach
post 15.10.2011, 10:35:35
Post #1





Grupa: Zarejestrowani
Postów: 999
Pomógł: 30
Dołączył: 14.01.2007
Skąd: wiesz ?

Ostrzeżenie: (0%)
-----


Hej,

Muszę zrobić w panelu adminisracyjnym strony możliwość generowania kodów dostępu.

Use case: Użyszkodnik loguje się -> podaje ilość kodów do wygenerowania -> dostaję listę kodów -> akceptuje i są one zapisywane w bazie / lub nie

Zastanawia mnie jak zrealizować generator. W przypadku jeśli ma zostać wygenerowanych powiedzmy 1000 kodów to trochę mało wydajnym wydaje się być generowanie ich z poziomu PHP i sprawdzanie każdego czy już taki istnieje. Rozważałem generowanie ich przez sh1() bądź md5() z jakiegoś wewnętrznego identyfikatora, ale wtedy wychodzą one trochę za długie. Nie chciałbym żeby miały one więcej niż 9 znaków.

W ogóle to najchętniej całą odpowiedzialność za ich generowanie przerzuciłbym na bazę danych tylko pisanie po to procedury składowej której czas wykonania będzie taki sam jak ewentualnego rozwiązania w skrypcie mija się trochę z celem bo baza jest na tej samej maszynie.

Jestem otwarty na wszelkiego rodzaju pomysły i sugestie.
Dzięki
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 18)
croc
post 15.10.2011, 11:07:07
Post #2





Grupa: Zarejestrowani
Postów: 706
Pomógł: 108
Dołączył: 12.03.2010

Ostrzeżenie: (0%)
-----


Możesz na przykład stworzyć w bazie tabelę z gotowymi kodami, które zostały wygenerowane wcześniej i sprawdzone pod kątem unikalności (zresztą wystarczy nałożyć na kolumnę z kodami parametr UNIQUE dla 100% pewności). A samo generowanie kodów to już wolna amerykanka.
Go to the top of the page
+Quote Post
Crozin
post 15.10.2011, 12:03:14
Post #3





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Nie masz się o co martwić o wydajność przy generowaniu raptem 1000 kodów. Napisz tylko dokładnie jakie jeszcze warunki muszą spełnić te kody, bo wspominasz coś o unikalności, ale nie podałeś dokładnie jakiej.
Go to the top of the page
+Quote Post
Fifi209
post 15.10.2011, 12:08:05
Post #4





Grupa: Zarejestrowani
Postów: 4 655
Pomógł: 556
Dołączył: 17.03.2009
Skąd: Katowice

Ostrzeżenie: (0%)
-----


Skoro potrzebujesz powiedzmy 9 znaków a md5 ma ich 32 to substr i sobie wytnij ze środka 9 znaków.

@down
Oczywiście, jakoś z rozpędu dałem _
Poprawione

Ten post edytował Fifi209 15.10.2011, 14:09:34


--------------------
Zainteresowania: C#, PHP, JS, SQL, AJAX, XML, C dla AVR
Chętnie pomogę, lecz zanim napiszesz: Wujek Google , Manual PHP
Go to the top of the page
+Quote Post
croc
post 15.10.2011, 12:31:39
Post #5





Grupa: Zarejestrowani
Postów: 706
Pomógł: 108
Dołączył: 12.03.2010

Ostrzeżenie: (0%)
-----


Jeśli już to substr. Ja kiedyś wycinałem z md5 fragment rozpoczynając od losowej pozycji. Możesz też zrobić sobie tablicę z dopuszczalnymi znakami i w pętli for dodawać do łańcucha znaków losowe elementy tej tablicy - wtedy masz pełną losowość.
Go to the top of the page
+Quote Post
CMG
post 15.10.2011, 13:17:08
Post #6





Grupa: Zarejestrowani
Postów: 6
Pomógł: 0
Dołączył: 15.10.2011

Ostrzeżenie: (0%)
-----


Ja jak muszę wygenerować jakieś losowe ciągi to korzystam zawsze z jednej niezawodnej funkcji.
  1. function generujKod($dlugoscKodu) {
  2. //$znaki = "abcdefghijkmnoprstuwxyzq"; //bez małego L
  3. $znaki .= "ABCDEFGHIJKLMNPRSTUWZYXQ"; // bez O
  4. $znaki .= "123456789"; // bez 0
  5. $dl = strlen($znaki) - 1;
  6. for($i =0; $i < $dlugoscKodu; $i++)
  7. {
  8. $losuj = rand(0, $dl);
  9. $wynik .= $znaki[$losuj];
  10. }
  11. return $wynik;
  12. };

Małe znaki są wyłączone bo ja akurat ich nie potrzebowałem ostatnio jak używałem tej funkcji, wystarczy usunąć "//".
Małe L usunięte żeby się nie myliło z 1. To samo z O i 0.
Zawsze można dodać z powrotem jeżeli się używa czcionki gdzie można odróżnić te podobne do siebie znaki.

I do tego można dodać zwykłą pętlę generującą i dodającą kody do bazy

  1. $ilosc = 1000; // ilość kodów do wygenerowania
  2. $dlugosc = 9; // długość generowanego kodu
  3.  
  4. for($i=0;$i<$ilosc;$i++){
  5. $kodzik = generujKod($dlugosc);
  6. mysql_query("INSERT INTO `baza_kodow` (kod,uzyty) VALUES ('$kodzik','0')");
  7. }


No nie ma 100% gwarancji że nie wygeneruje się taki sam kod. Jest bardzo mało prawdopodobne, ale rzeczywiście można to zabezpieczyć nadaniem UNIQUE na kolumnę "kod".

Ten post edytował CMG 15.10.2011, 13:19:22
Go to the top of the page
+Quote Post
qrooel
post 15.10.2011, 13:41:28
Post #7





Grupa: Zarejestrowani
Postów: 306
Pomógł: 42
Dołączył: 25.03.2010
Skąd: Kraków

Ostrzeżenie: (0%)
-----


W moim kodzie wygenerowanie 10k 9-znakowych tokenów trwało niecałą sekundę, więc o wydajność nie martwiłbym się. ;p

Potrzebowałem ostatnio czegoś takiego na szybkości, że tak powiem.

  1. <?php
  2. /*
  3. * GENERATOR LOSOWYCH TOKENÓW/ZNAKÓW
  4. *
  5. * MOŻLIWE TOKENY: LITERY (DUŻE I MAŁE), CYFRY, ZNAKI SPECJALNE ORAZ WSZYSTKIE NA RAZ
  6. *
  7. * PRZYKŁAD UŻYCIA:
  8. *
  9. * require('classes/class.randomtoken.php'); // dołączanie biblioteki
  10. *
  11. * $token = new RandomToken; // tworzenie obiektu
  12. * $token->setBigAlpha(); // ustawianie małych i wielkich liter, bez tej linijki będą tylko małe litery
  13. * $token->setAlphaNumericSpecial(); // wybór rodzaju wygenerowanego tokena, dostępne:
  14. * // $this->setNumeric(); // tylko cyfry
  15. * // $this->setAlpha(); // tylko litery
  16. * // $this->setSpecial(); // tylko znaki specjalne
  17. * // $this->setAlphaNumeric(); // cyfry i litery
  18. * // $this->setAlphaNumericSpecial(); // cyfry, litery i znaki specjalne
  19. * echo $token->generate(15); // zwraca token o podanej długości w parametrze
  20. */
  21.  
  22.  
  23. class RandomToken
  24. {
  25. private $_pattern = array();
  26. private $_numeric = array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9");
  27. private $_alpha = array("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "r", "s", "t", "u", "w", "x", "y");
  28. private $_alphaBig = array("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "k", "L", "M", "N", "O", "P", "R", "S", "T", "U", "W", "X", "Y");
  29. private $_special = array("!", "@", "#", "_", "-", "@", "#", "_", "-");
  30.  
  31.  
  32. public function setNumeric()
  33. {
  34. $this->_pattern = $this->_numeric;
  35. }
  36.  
  37. public function setAlpha()
  38. {
  39. $this->_pattern = $this->_alpha;
  40. }
  41.  
  42. public function setBigAlpha()
  43. {
  44. $this->_alpha = array_merge((array)$this->_alpha, (array)$this->_alphaBig);
  45. }
  46.  
  47. public function setSpecial()
  48. {
  49. $this->_pattern = $this->_special;
  50. }
  51.  
  52. public function setAlphaNumeric()
  53. {
  54. $this->_pattern = array_merge((array)$this->_alpha, (array)$this->_numeric);
  55. }
  56.  
  57. public function setAlphaNumericSpecial()
  58. {
  59. $this->_pattern = array_merge((array)$this->_alpha, (array)$this->_numeric, (array)$this->_special);
  60. }
  61.  
  62. public function generate($count)
  63. {
  64. for($y = 1; $y <= $count; $y++)
  65. {
  66. $rand = array_rand($this->_pattern);
  67. $result .= $this->_pattern[$rand];
  68. }
  69.  
  70. return $result;
  71. }
  72. }


Użycie:

  1. require('classes/class.randomtoken.php');
  2.  
  3. $token = new RandomToken;
  4. $token->setBigAlpha();
  5. $token->setAlphaNumericSpecial();
  6.  
  7. $i = 0;
  8. while($i <= 10000)
  9. {
  10. echo $token->generate(9);
  11. echo '<br />';
  12. $i++;
  13. }


Ważne, że spełnia swoją rolę. ;P

Edit: tamten był oczywiście niepoprawny, teraz jest 'wydajniejszy'.

Ten post edytował qrooel 15.10.2011, 22:29:00


--------------------
Strony WWW: http://arscreo.pl
Go to the top of the page
+Quote Post
Fifi209
post 15.10.2011, 14:16:21
Post #8





Grupa: Zarejestrowani
Postów: 4 655
Pomógł: 556
Dołączył: 17.03.2009
Skąd: Katowice

Ostrzeżenie: (0%)
-----


Zamiast kombinować: uniqid

Co do Twojej "klasy":
Działa błędnie.

Pierwszym błędem jest warunek:
  1. for($i = 0; $i <= $array_count; $i++)

Skoro liczysz od zera a podajesz 9 to nie wygeneruje 9 tylko 10 znaków.

Ten post edytował Fifi209 15.10.2011, 14:16:56


--------------------
Zainteresowania: C#, PHP, JS, SQL, AJAX, XML, C dla AVR
Chętnie pomogę, lecz zanim napiszesz: Wujek Google , Manual PHP
Go to the top of the page
+Quote Post
starach
post 15.10.2011, 15:06:24
Post #9





Grupa: Zarejestrowani
Postów: 999
Pomógł: 30
Dołączył: 14.01.2007
Skąd: wiesz ?

Ostrzeżenie: (0%)
-----


Cytat(croc @ 15.10.2011, 12:07:07 ) *
Możesz na przykład stworzyć w bazie tabelę z gotowymi kodami, które zostały wygenerowane wcześniej i sprawdzone pod kątem unikalności (zresztą wystarczy nałożyć na kolumnę z kodami parametr UNIQUE dla 100% pewności). A samo generowanie kodów to już wolna amerykanka.
I tak właśnie mam w bazie jedno pole z kodem UNIQUE i jedno z datą dodania.

Cytat(Crozin @ 15.10.2011, 13:03:14 ) *
Nie masz się o co martwić o wydajność przy generowaniu raptem 1000 kodów. Napisz tylko dokładnie jakie jeszcze warunki muszą spełnić te kody, bo wspominasz coś o unikalności, ale nie podałeś dokładnie jakiej.
Samo generowanie to w sumie nie problem, ale jeśli mam sprawdzać istnienie każdego kodu w bazie za pomocą SELECT cośtam to wydajność może dostać mocnego kopa w jaja i to mnie właśnie trochę martwii. Dlatego szukam sposobu na generowanie tych kodów w jakiś ciągły sposób żeby wyeliminować konieczność sprawdzania ich istnienia w bazie.

Cytat(Fifi209 @ 15.10.2011, 13:08:05 ) *
Skoro potrzebujesz powiedzmy 9 znaków a md5 ma ich 32 to substr i sobie wytnij ze środka 9 znaków.

@down
Oczywiście, jakoś z rozpędu dałem _
Poprawione
W tym wypadku wymagane będzie składowanie jakiegoś licznika i nie wiadomo w sumie jak tak wycięty ciąg znaków będzie się często powarzać. No w sumie można to też na microtime zamiast licznika zrobić.

Cytat(CMG @ 15.10.2011, 14:17:08 ) *
Ja jak muszę wygenerować jakieś losowe ciągi to korzystam zawsze z jednej niezawodnej funkcji.
(...)
Niemalże identycznego kodu używam do funkcji przypominania hasła, które jest potem wysyłane na adres email. smile.gif
Go to the top of the page
+Quote Post
croc
post 15.10.2011, 15:06:48
Post #10





Grupa: Zarejestrowani
Postów: 706
Pomógł: 108
Dołączył: 12.03.2010

Ostrzeżenie: (0%)
-----


qrooel - po co używasz powolnego shuffle tak wiele razy? Shuffle to shuffle - miesza całą tablicę. Do wybierania losowych elementów używa się array_rand.
Go to the top of the page
+Quote Post
Fifi209
post 15.10.2011, 17:01:16
Post #11





Grupa: Zarejestrowani
Postów: 4 655
Pomógł: 556
Dołączył: 17.03.2009
Skąd: Katowice

Ostrzeżenie: (0%)
-----


Nie musisz robić selectów przecież w ogóle. Zakładając, że dodajesz każdy oddzielnie i masz to unique to w przypadku, gdy wartość się powtórzy dostaniesz false.


--------------------
Zainteresowania: C#, PHP, JS, SQL, AJAX, XML, C dla AVR
Chętnie pomogę, lecz zanim napiszesz: Wujek Google , Manual PHP
Go to the top of the page
+Quote Post
qrooel
post 15.10.2011, 17:01:31
Post #12





Grupa: Zarejestrowani
Postów: 306
Pomógł: 42
Dołączył: 25.03.2010
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Tak jak pisałem, napisane szybko żeby działało. Wiadomo, że pasowałoby to poprawić. Co do array_rand -> oczywiście, że tak powinno się to zrobić. ;P

Ten post edytował qrooel 15.10.2011, 17:09:57


--------------------
Strony WWW: http://arscreo.pl
Go to the top of the page
+Quote Post
croc
post 15.10.2011, 17:09:54
Post #13





Grupa: Zarejestrowani
Postów: 706
Pomógł: 108
Dołączył: 12.03.2010

Ostrzeżenie: (0%)
-----


Napisane na szybko? Pieściłeś się z tymi metodami do patternu jak z jajkiem, a podstawy kuleją.
Go to the top of the page
+Quote Post
starach
post 15.10.2011, 18:19:31
Post #14





Grupa: Zarejestrowani
Postów: 999
Pomógł: 30
Dołączył: 14.01.2007
Skąd: wiesz ?

Ostrzeżenie: (0%)
-----


Cytat(Fifi209 @ 15.10.2011, 18:01:16 ) *
Nie musisz robić selectów przecież w ogóle. Zakładając, że dodajesz każdy oddzielnie i masz to unique to w przypadku, gdy wartość się powtórzy dostaniesz false.
Tak wiem, ale tylko jeśli miałbym ich przed dodaniem nie wyświetlać do zaakceptowania. smile.gif


Go to the top of the page
+Quote Post
Fifi209
post 15.10.2011, 18:28:39
Post #15





Grupa: Zarejestrowani
Postów: 4 655
Pomógł: 556
Dołączył: 17.03.2009
Skąd: Katowice

Ostrzeżenie: (0%)
-----


Jeżeli musisz sprawdzać, to każda metoda będzie wymagała selectów.


--------------------
Zainteresowania: C#, PHP, JS, SQL, AJAX, XML, C dla AVR
Chętnie pomogę, lecz zanim napiszesz: Wujek Google , Manual PHP
Go to the top of the page
+Quote Post
Crozin
post 15.10.2011, 18:38:53
Post #16





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


1. Generujesz 1000 kodów (możesz w sumie wygenerować sobie ich nieco więcej na poczet zduplikowanych).
2.
  1. SELECT kod FROM kody WHERE kod IN('kod1', 'kod2', ..., 'kodn');

3. Usuwasz z tablicy wygenerowanych kodów te, które zwróciło zapytanie - array_intersect.
4. Jeżeli tablica ma ponad 1000 elementów przycinasz ją - array_slice.
5. Jeżeli tablica ma poniżej 1000 elementów powtarzasz całość łącząc na końcu starą i nową tablicę.
Go to the top of the page
+Quote Post
croc
post 15.10.2011, 18:43:44
Post #17





Grupa: Zarejestrowani
Postów: 706
Pomógł: 108
Dołączył: 12.03.2010

Ostrzeżenie: (0%)
-----


Nie lepiej wsadzić do bazy jakieś milion unikalnych kodów samemu i dodać kolumnę określającą czy kod został użyty czy nie lub też bardziej wyrafinowane przypisywanie kodów do czegoś (co oznacza, że jest zużyty)?
Go to the top of the page
+Quote Post
Fifi209
post 15.10.2011, 18:47:27
Post #18





Grupa: Zarejestrowani
Postów: 4 655
Pomógł: 556
Dołączył: 17.03.2009
Skąd: Katowice

Ostrzeżenie: (0%)
-----


Swoją drogą, po co te kody?


--------------------
Zainteresowania: C#, PHP, JS, SQL, AJAX, XML, C dla AVR
Chętnie pomogę, lecz zanim napiszesz: Wujek Google , Manual PHP
Go to the top of the page
+Quote Post
qrooel
post 15.10.2011, 23:21:58
Post #19





Grupa: Zarejestrowani
Postów: 306
Pomógł: 42
Dołączył: 25.03.2010
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Cytat(croc @ 15.10.2011, 16:06:48 ) *
qrooel - po co używasz powolnego shuffle tak wiele razy? Shuffle to shuffle - miesza całą tablicę. Do wybierania losowych elementów używa się array_rand.



Poprawione. Faktycznie, na próbie w pętli wykonywanej 10000 razy shuffle wykonuje operację o prawie sekundę dłużej niż array_rand.


--------------------
Strony WWW: http://arscreo.pl
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 19.07.2025 - 20:47