PDA

Visualizza la versione completa : (JAVA) generare password


Prazision
01-03-2005, 20:02
questa classe:



import java.util.*;

public class PwdGenerator {

/** Creates a new instance of GeneratePwd */
public PwdGenerator() {

}

Random rnd = new Random();

public static void main(String arfgv[])
{
PwdGenerator a = new PwdGenerator();
System.out.println(a.getPWD());
PwdGenerator a2 = new PwdGenerator();
System.out.println(a2.getPWD());

}

public String getPWD() {

//decido dimensione password
int dim = 8;//rnd.nextInt(5);
//dim = dim+6;
//decido la quantità di cifre numeriche
int num = rnd.nextInt(dim-4)+1;
num= num+2;
//decido la quantità di cifre alfa
int alfa = dim-num;
int appoggio=0;
String pass="";
int alterna=0;
int contnum=1;
int contalfa=1;
for (int i=1;i<=dim;i++) {
alterna = rnd.nextInt(2);
if (contalfa>alfa){alterna=0;}
else{if (contnum>num) {alterna=1;}
}
if (alterna==1) {contalfa++;
appoggio = rnd.nextInt(25);
switch (appoggio) {
case 0 : pass = pass+"A";break;
case 1 : pass = pass+"B";break;
case 2 : pass = pass+"C";break;
case 3 : pass = pass+"D";break;
case 4 : pass = pass+"E";break;
case 5 : pass = pass+"F";break;
case 6 : pass = pass+"G";break;
case 7 : pass = pass+"H";break;
case 8 : pass = pass+"I";break;
case 9 : pass = pass+"J";break;
case 10 : pass = pass+"K";break;
case 11 : pass = pass+"L";break;
case 12 : pass = pass+"M";break;
case 13 : pass = pass+"N";break;
case 14 : pass = pass+"O";break;
case 15 : pass = pass+"P";break;
case 16 : pass = pass+"Q";break;
case 17 : pass = pass+"R";break;
case 18 : pass = pass+"S";break;
case 19 : pass = pass+"T";break;
case 20 : pass = pass+"U";break;
case 21 : pass = pass+"W";break;
case 22 : pass = pass+"X";break;
case 23 : pass = pass+"Y";break;
case 24 : pass = pass+"Z";break;
}
}
if (alterna==0) {contnum++;
appoggio = rnd.nextInt(10);
switch (appoggio) {
case 0 : pass = pass+"0";break;
case 1 : pass = pass+"1";break;
case 2 : pass = pass+"2";break;
case 3 : pass = pass+"3";break;
case 4 : pass = pass+"4";break;
case 5 : pass = pass+"5";break;
case 6 : pass = pass+"6";break;
case 7 : pass = pass+"7";break;
case 8 : pass = pass+"8";break;
case 9 : pass = pass+"9";break;
}
}
}

return pass;
}

}

viene richiamata da alcune pagine jsp(col codice che segue) per creare una password:
PwdGenerator a = new PwdGenerator();
String pws =a.getPWD();

Io penso che se la pagina che contiene la creazione della password viene richiamata contemporaneamente da 2 utenti(unpo' come avviene nel main che ho mostrato) le password generate sono uguali(per via delle caratteristiche della classe Random )


La mia paura è fondata o si tratta di un'ipotesi semimpossibile?
Come si puo' rimediare?

ciao grazie

Prazision
02-03-2005, 15:00
Ho notato che se metto

static Random rnd = new Random();
invece di Random rnd = new Random();
e utilizzo un metodo static cosi:

public static void main(String arfgv[])
{
PwdGenerator a = new PwdGenerator();
System.out.println(a.getPWD());

PwdGenerator a2 = new PwdGenerator();
System.out.println(a2.getPWD());
}

ottengo 2 password diverse (al contrario di quando rnd non è static)

Perchè succede questo?
se le chiamate sono istantanee il seme di Random non dovrebbe essere cmq
lo stesso??

Forse perchè l'oggetto rnd è condiviso dalle classi istanziate e quindi il metodo nextInt() viene eseguito dallo stesso oggetto(e quindi per forza in maniera sequenziale, dando 2 risultati diversi)?

E quindi tale cosa potrebbe risolvere il mio problema nel senso che anche se ci fossero 2 chiamate a 2 pagine nello stesso istante la password generate sarebbero diverse(unpo' come nel main della mia classe)?

spero di essermi spiegato grazie

Prazision
02-03-2005, 15:58
forse però non è tanto bello avere lo stesso oggetto Random condiviso dai vari oggetti PwdGenerator nelle pagine jsp, che problemi potrebbe dare?

LeleFT
02-03-2005, 16:10
Io ti propongo una scelta diversa: hai provato ad utilizzare Math.random()? E' un metodo statico della classe Math che restituisce un valore compreso fra 0.0 (incluso) e 1.0 (escluso). Applicando le moltiplicazioni e il modulo puoi ottenere lo stesso risultato senza dover istanziare alcun generatore. Esempio:


// Estraggo un numero a caso compreso fra 1 e 6 (lancio del dado):
int numero = ((int)(Math.random() * 10000) % 6 ) + 1;

Il valore 10000 che ho usato serve solo per spostare la virgola decimale in modo da ottenere un valore intero maggiore di 0, quindi puoi utilizzare qualsiasi potenza di 10, ni base alla precisione che ti serve.


Ciao. :ciauz:

Prazision
02-03-2005, 16:19
appena posso guardo anche Math.random() ma sulla mia soluzione non sai dirmi nulla?


graz

LeleFT
02-03-2005, 16:28
Per quanto riguarda la tua soluzione, ho notato solo ora che tu, nel main, generi due istanze della stessa classe.

Settando statico l'oggetto Random, fai in modo che entrambe le istanze condividano lo stesso oggetto, mentre avendo un oggetto non statico, ogni istanza possiederà la propria copia dell'oggetto.

A questo punto credo che le due chiamate siano effettuate talmente velocemente che il seed (seme) viene impostato allo stesso valore (anche se la cosa mi suona abbastanza strana). Il costruttore vuoto di Random, infatti, fa sì che il seme venga inizializzato con il valore di System.getCurrentTimeMillis() ed è possibile che tale valore sia uguale durante le due chiamate, istanziando due generatori uguali (probabilmente la granularità di System.getCurrentTimeMillis() non è sufficiente a garantire due valori diversi).

Ciao. :ciauz:

Prazision
02-03-2005, 16:33
grazie

LeleFT
02-03-2005, 16:44
Ho effettuato una prova e ho la "quasi" certezza di ciò che ho detto prima:


public class Prova {
public static void main(String [] args) {
for (int i=0; i<100; i++)
System.out.println(System.currentTimeMillis());
}
}
Questo codice stampa a video il valore corrente del timer di sistema (il metodo si chiama currentTimeMillis() e non getCurrentTimeMillis() come ho erroneamente scritto prima).
Come si può notare, a video compare più volte lo stesso valore e cambia ogni tot chiamate al metodo (questo tot dipende, ovviamente, dalla granularità del sistema oltre che dal tipo e dalla velocità del processore). Nel mio caso ho effettuato il test su un PIII 700 MHz ed il valore cambia ogni 32 chiamate circa, con una granularità di 10 millisecondi.
Questo significa che, con due chiamate successive, ho un'alta probabilità che il valore restituito da System.currentTimeMillis() sia lo stesso e che quindi due generatori di numeri casuali possano essere inizializzati con lo stesso identico seme, risultando, pertanto, del tutto identici.

Per questo ti consiglio di utilizzare un generatore statico oppure, meglio ancora, utilizzare il generatore di Math.random() che è statico e non può essere toccato dal tuo programma.


Ciao. :ciauz:

Prazision
02-03-2005, 17:08
appena posso guardo tutto e ti dico, grazie mille

Loading