Generátor hesla v PHP

Na chvíli odbočím od politických příspěvků a vrátím se ke svému hlavnímu oboru, kterým je programování. Včera jsem v rámci programování svého sytému potřeboval funkci, která mi vygeneruje nějaké bezpečné heslo a řekl jsem si, že by se třeba mohla někomu hodit, tak ji sem dám k dispozici i s nějakým vysvětlením.

Nejprve v rychlosti teorie. Chceme, aby funkce vygenerovala textový řetězec, který má x znaků, z toho y velkých písmen, z čísel a w speciálních znaků. V proměnných jsou tato čísla uložená proto, aby byla funkce flexibilní a dala se v tomto směru jednoduše upravit.

Nejprve tedy funkci deklarujeme

function generate_password($x=12;$y=4;$z=3;$w=2){

}

Pokud funkce nedostane žádný argument, vygeneruje 12-místné heslo se 4 velkými písmeny, 3 čísly a 2 speciálními znaky. Ve funkci nejprve deklarujeme textovou proměnnou. Tu následně naplníme pomocí cyklu for x náhodnými malými písmeny. Využijeme k tomu funkci chr(), která nám vrací znak podle jeho ASCII kódu a funkci rand(), která nám vrátí pseudonáhodné číslo v zadaném rozmezí. V ASCII tabulce jsou malá písmena na pozicích 97 - 122.

password = ""; 
for($i=0;$i<$x;$i++){
      $password[$i] = chr(rand(97,122)); 
}
Nyní máme v proměnné $password pole znaků o x prvcích. Teď potřebujeme, aby funkce vybrala y náhodných prvků a ty změnila na náhodně vygenerovaná velká písmena. Zároveň ale musíme myslet na to, že funkce nesmí přepsat dvakrát to stejné místo, neboť potom by to ztrácelo na účinnosti, musíme zařídit, aby přepsala vždy jiný znak. A to samé platí i pro čísla a speciální znaky. Proto si vytvoříme prázdné pole $chars, do kterého budeme ukládat čísla znaků, které jsme již upravili. Před každou změnou se potom pomocí cyklu do-while a funkce in_array() zeptáme, jestli jsme náhodou už tento znak nepřepsali a pokud ano, vybereme nový. Pro ty, co se nesetkali s celkem neobvyklým cyklem do-while, funguje podobně jako while, akorát opačně, tedy podmínka se vyhodnotí až po vykonání příkazu a rozhodne, jestli ho provede znovu. Je tím zaručeno, že se příkaz alespoň jednou provede, což je v našem případě žádoucí.


$chars = array();
for($i=0;$i<$y;$i++){
      do{$number = rand(0,$x-1);}
      while(in_array($number, $chars));
      //vložení čísla přepsaného znaku do pole
      array_push($chars, $number);
      //velká písmena jsou na pozicích 65 - 90
      $password[$number]=chr(rand(65,90));
 }
 Nyní už stačí jen dvakrát zkopírovat tento for cyklus, místo $y napsat $z a $w a 65,90 přepsat na 48,57 (čísla) a 35,38 (několik speciálních znaků). Celá funkce může vypadat nějak takto

function generate_password($x=12,$y=4,$z=3,$w=2){
    $password = "";
    for($i=0;$i<$x;$i++){
      $password[$i] = chr(rand(97,122));
    }
    $chars = array();
    for($i=0;$i<$y;$i++){
      do{$number = rand(0,$x-1);}
      while(in_array($number, $chars));
      array_push($chars, $number);
      $password[$number]=chr(rand(65,90));
    }
    for($i=0;$i<$z;$i++){
      do{$number = rand(0,$x-1);}
      while(in_array($number, $chars));
      array_push($chars, $number);
      $password[$number]=chr(rand(48,57));
    }
    for($i=0;$i<$w;$i++){
      do{$number = rand(0,$x-1);}
      while(in_array($number, $chars));
      array_push($chars, $number);
      $password[$number]=chr(rand(35,38));
    }
    return join("",$password);
  }
Na konci akorát uděláme z textového pole $password ucelený řetězec pomocí funkce join(). Výsledkem je flexibilní funkce generující heslo v takovém formátu, jaký budete chtít. Pozor dávejte na jednu věc - ve funkci jsem neošetřil situaci, kdy je součet y+z+w vyšší, než x. V takovém případě by funkce skončila nekončeným cyklem, neboť do-while by neustále hledal volnou pozici, která by již neexistovala. Jestli chcete, můžete si tu podmínku doprogramovat :)

Komentáře

Populární příspěvky z tohoto blogu

Jak si ve Skyrimu postavit vlastní dům

8 důvodů, proč je ve Skyrimu lepší být Pánem Upírů než Vlkodlakem

Proměňte svoje NHL 09 na NHL 12