generare - stringhe random java




Come generare una stringa alfanumerica casuale? (20)

Algoritmo

Per generare una stringa casuale, concatena i caratteri estratti casualmente dall'insieme di simboli accettabili fino a quando la stringa raggiunge la lunghezza desiderata.

Implementazione

Ecco un codice abbastanza semplice e molto flessibile per la generazione di identificatori casuali. Leggi le informazioni che seguono per importanti note applicative.

import java.security.SecureRandom;
import java.util.Locale;
import java.util.Objects;
import java.util.Random;

public class RandomString {

    /**
     * Generate a random string.
     */
    public String nextString() {
        for (int idx = 0; idx < buf.length; ++idx)
            buf[idx] = symbols[random.nextInt(symbols.length)];
        return new String(buf);
    }

    public static final String upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    public static final String lower = upper.toLowerCase(Locale.ROOT);

    public static final String digits = "0123456789";

    public static final String alphanum = upper + lower + digits;

    private final Random random;

    private final char[] symbols;

    private final char[] buf;

    public RandomString(int length, Random random, String symbols) {
        if (length < 1) throw new IllegalArgumentException();
        if (symbols.length() < 2) throw new IllegalArgumentException();
        this.random = Objects.requireNonNull(random);
        this.symbols = symbols.toCharArray();
        this.buf = new char[length];
    }

    /**
     * Create an alphanumeric string generator.
     */
    public RandomString(int length, Random random) {
        this(length, random, alphanum);
    }

    /**
     * Create an alphanumeric strings from a secure generator.
     */
    public RandomString(int length) {
        this(length, new SecureRandom());
    }

    /**
     * Create session identifiers.
     */
    public RandomString() {
        this(21);
    }

}

Esempi di utilizzo

Crea un generatore non sicuro per identificatori di 8 caratteri:

RandomString gen = new RandomString(8, ThreadLocalRandom.current());

Crea un generatore sicuro per identificatori di sessione:

RandomString session = new RandomString();

Crea un generatore con codici facili da leggere per la stampa. Le stringhe sono più lunghe delle stringhe alfanumeriche complete per compensare l'utilizzo di un numero inferiore di simboli:

String easy = RandomString.digits + "ACEFGHJKLMNPQRUVWXYabcdefhijkprstuvwx";
RandomString tickets = new RandomString(23, new SecureRandom(), easy);

Utilizzare come identificativi di sessione

La generazione di identificativi di sessione che potrebbero essere unici non è abbastanza buona, oppure potresti semplicemente usare un semplice contatore. Gli attaccanti dirottano le sessioni quando vengono utilizzati identificatori prevedibili.

C'è tensione tra lunghezza e sicurezza. Identificatori più brevi sono più facili da indovinare, perché ci sono meno possibilità. Ma gli identificatori più lunghi consumano più spazio di archiviazione e larghezza di banda. Una serie più ampia di simboli aiuta, ma potrebbe causare problemi di codifica se gli identificatori sono inclusi negli URL o reinseriti a mano.

La fonte sottostante di casualità, o entropia, per gli identificatori di sessione dovrebbe provenire da un generatore di numeri casuali progettato per la crittografia. Tuttavia, l'inizializzazione di questi generatori può a volte essere computazionalmente costosa o lenta, quindi è necessario fare uno sforzo per riutilizzarli quando possibile.

Utilizzare come identificatori di oggetto

Non tutte le applicazioni richiedono sicurezza. L'assegnazione casuale può essere un modo efficace per più entità di generare identificatori in uno spazio condiviso senza alcun coordinamento o partizionamento. La coordinazione può essere lenta, specialmente in un ambiente cluster o distribuito, e la suddivisione di uno spazio causa problemi quando le entità finiscono con azioni troppo piccole o troppo grandi.

Gli identificatori generati senza prendere misure per renderli imprevedibili dovrebbero essere protetti con altri mezzi se un utente malintenzionato potrebbe essere in grado di visualizzarli e manipolarli, come accade nella maggior parte delle applicazioni web. Ci dovrebbe essere un sistema di autorizzazione separato che protegge gli oggetti il ​​cui identificatore può essere indovinato da un utente malintenzionato senza permesso di accesso.

Bisogna anche prestare attenzione all'utilizzo di identificatori sufficientemente lunghi da rendere improbabili le collisioni dato il numero totale previsto di identificatori. Questo è indicato come "il paradosso del compleanno". La probabilità di una collisione, p , è approssimativamente n 2 / (2q x ), dove n è il numero di identificatori effettivamente generati, q è il numero di simboli distinti nell'alfabeto e x è la lunghezza degli identificatori. Questo dovrebbe essere un numero molto piccolo, come 2 -50 o meno.

Questo risultato mostra che la possibilità di collisione tra gli identificatori di 500 caratteri a 15 caratteri è di circa 2 -52 , che è probabilmente meno probabile di errori non rilevati dai raggi cosmici, ecc.

Confronto con UUID

Secondo le loro specifiche, gli UUID non sono progettati per essere imprevedibili e non dovrebbero essere usati come identificatori di sessione.

Gli UUID nel loro formato standard occupano molto spazio: 36 caratteri per soli 122 bit di entropia. (Non tutti i bit di un UUID "casuale" vengono selezionati casualmente). Una stringa alfanumerica scelta a caso racchiude più entropia in soli 21 caratteri.

Gli UUID non sono flessibili; hanno una struttura e un layout standardizzati. Questa è la loro principale virtù e la loro principale debolezza. Quando si collabora con una parte esterna, la standardizzazione offerta dagli UUID può essere utile. Per uso puramente interno, possono essere inefficienti.

Stavo cercando un semplice algoritmo Java per generare una stringa alfanumerica pseudo-casuale. Nella mia situazione verrebbe utilizzato come identificatore di sessione / chiave univoco che "verosimilmente" sarebbe unico oltre la generazione di 500K + (le mie esigenze non richiedono in realtà nulla di molto più sofisticato). Idealmente, sarei in grado di specificare una lunghezza a seconda delle mie esigenze di unicità. Ad esempio, una stringa generata di lunghezza 12 potrebbe sembrare qualcosa come "AEYGF7K0DM1X" .


  1. Cambia i caratteri della stringa secondo i tuoi requisiti.

  2. La stringa è immutabile. Qui StringBuilder.append è più efficiente della concatenazione di stringhe.


public static String getRandomString(int length) {
       final String characters = "[email protected]#$%^&*()_+";
       StringBuilder result = new StringBuilder();
       while(length > 0) {
           Random rand = new Random();
           result.append(characters.charAt(rand.nextInt(characters.length())));
           length--;
       }
       return result.toString();
    }

Eccolo in Java:

import static java.lang.Math.round;
import static java.lang.Math.random;
import static java.lang.Math.pow;
import static java.lang.Math.abs;
import static java.lang.Math.min;
import static org.apache.commons.lang.StringUtils.leftPad

public class RandomAlphaNum {
  public static String gen(int length) {
    StringBuffer sb = new StringBuffer();
    for (int i = length; i > 0; i -= 12) {
      int n = min(12, abs(i));
      sb.append(leftPad(Long.toString(round(random() * pow(36, n)), 36), n, '0'));
    }
    return sb.toString();
  }
}

Ecco un esempio di esecuzione:

scala> RandomAlphaNum.gen(42)
res3: java.lang.String = uja6snx21bswf9t89s00bxssu8g6qlu16ffzqaxxoy

Ho trovato questa soluzione che genera una stringa esadecimale casuale codificata. Il test dell'unità fornito sembra confermare il mio caso d'uso principale. Anche se, è leggermente più complesso di alcune delle altre risposte fornite.

/**
 * Generate a random hex encoded string token of the specified length
 *  
 * @param length
 * @return random hex string
 */
public static synchronized String generateUniqueToken(Integer length){ 
    byte random[] = new byte[length];
    Random randomGenerator = new Random();
    StringBuffer buffer = new StringBuffer();

    randomGenerator.nextBytes(random);

    for (int j = 0; j < random.length; j++) {
        byte b1 = (byte) ((random[j] & 0xf0) >> 4);
        byte b2 = (byte) (random[j] & 0x0f);
        if (b1 < 10)
            buffer.append((char) ('0' + b1));
        else
            buffer.append((char) ('A' + (b1 - 10)));
        if (b2 < 10)
            buffer.append((char) ('0' + b2));
        else
            buffer.append((char) ('A' + (b2 - 10)));
    }
    return (buffer.toString());
}

@Test
public void testGenerateUniqueToken(){
    Set set = new HashSet();
    String token = null;
    int size = 16;

    /* Seems like we should be able to generate 500K tokens 
     * without a duplicate 
     */
    for (int i=0; i<500000; i++){
        token = Utility.generateUniqueToken(size);

        if (token.length() != size * 2){
            fail("Incorrect length");
        } else if (set.contains(token)) {
            fail("Duplicate token generated");
        } else{
            set.add(token);
        }
    }
}

Java fornisce un modo per farlo direttamente. Se non vuoi i trattini, sono facili da togliere. Basta usare uuid.replace("-", "")

import java.util.UUID;

public class randomStringGenerator {
    public static void main(String[] args) {
        System.out.println(generateString());
    }

    public static String generateString() {
        String uuid = UUID.randomUUID().toString();
        return "uuid = " + uuid;
    }
}

Produzione:

uuid = 2d7428a6-b58c-4008-8575-f05549f16316

L'utilizzo degli UUID non è sicuro, in quanto parti dell'UUID non sono affatto casuali. La procedura di @erickson è molto accurata, ma non crea stringhe della stessa lunghezza. Il seguente frammento di codice dovrebbe essere sufficiente:

/*
 * The random generator used by this class to create random keys.
 * In a holder class to defer initialization until needed.
 */
private static class RandomHolder {
    static final Random random = new SecureRandom();
    public static String randomKey(int length) {
        return String.format("%"+length+"s", new BigInteger(length*5/*base 32,2^5*/, random)
            .toString(32)).replace('\u0020', '0');
    }
}

Perché scegliere la length*5 . Assumiamo il caso semplice di una stringa casuale di lunghezza 1, quindi un carattere casuale. Per ottenere un carattere casuale contenente tutte le cifre 0-9 e i caratteri az, avremmo bisogno di un numero casuale compreso tra 0 e 35 per ottenere uno di ciascun carattere. BigInteger fornisce un costruttore per generare un numero casuale, distribuito uniformemente nell'intervallo da 0 to (2^numBits - 1) . Purtroppo 35 non è un numero che può essere ricevuto da 2 ^ numBits - 1. Quindi abbiamo due opzioni: O vai con 2^5-1=31 o 2^6-1=63 . Se avessimo scelto 2^6 avremmo molti numeri "inutili" / "più lunghi". Quindi 2^5 è l'opzione migliore, anche se perdiamo 4 caratteri (wz). Per generare una stringa di una certa lunghezza, possiamo semplicemente usare un numero 2^(length*numBits)-1 . L'ultimo problema, se vogliamo una stringa con una certa lunghezza, random potrebbe generare un piccolo numero, quindi la lunghezza non è soddisfatta, quindi dobbiamo applicare la stringa alla lunghezza richiesta in anticipo di zero.


Se sei felice di utilizzare le classi Apache, puoi utilizzare org.apache.commons.text.RandomStringGenerator (commons-text).

Esempio:

RandomStringGenerator randomStringGenerator =
        new RandomStringGenerator.Builder()
                .withinRange('0', 'z')
                .filteredBy(CharacterPredicates.LETTERS, CharacterPredicates.DIGITS)
                .build();
randomStringGenerator.generate(12); // toUpperCase() if you want

Poiché commons-lang 3.6, RandomStringUtils è deprecato.


Sorprendente nessuno qui lo ha suggerito ma:

import java.util.UUID

UUID.randomUUID().toString();

Facile.

Il vantaggio di questo è che gli UUID sono belli e lunghi e sono quasi impossibili da scontrarsi.

Wikipedia ha una buona spiegazione di ciò:

"... solo dopo aver generato 1 miliardo di UUID al secondo per i prossimi 100 anni, la probabilità di creare un solo duplicato sarebbe di circa il 50%."

http://en.wikipedia.org/wiki/Universally_unique_identifier#Random_UUID_probability_of_duplicates

I primi 4 bit sono il tipo di versione e 2 per la variante in modo da ottenere 122 bit di random. Quindi, se lo desideri , puoi troncare dalla fine per ridurre la dimensione dell'UUID. Non è raccomandato, ma hai ancora un sacco di casualità, abbastanza per i tuoi record di 500k facile.


Una soluzione breve e facile, ma utilizza solo caratteri minuscoli e numerici:

Random r = new java.util.Random ();
String s = Long.toString (r.nextLong () & Long.MAX_VALUE, 36);

La dimensione è di circa 12 cifre rispetto alla base 36 e non può essere ulteriormente migliorata in questo modo. Ovviamente puoi aggiungere più istanze.


l'utilizzo di Dollar dovrebbe essere semplice come:

// "0123456789" + "ABCDE...Z"
String validCharacters = $('0', '9').join() + $('A', 'Z').join();

String randomString(int length) {
    return $(validCharacters).shuffle().slice(length).toString();
}

@Test
public void buildFiveRandomStrings() {
    for (int i : $(5)) {
        System.out.println(randomString(12));
    }
}

emette qualcosa del genere:

DKL1SBH9UJWC
JH7P0IT21EA5
5DTI72EO6SFU
HQUMJTEBNF7Y
1HCR6SKYWGT7

Ecco una soluzione Scala:

(for (i <- 0 until rnd.nextInt(64)) yield { 
  ('0' + rnd.nextInt(64)).asInstanceOf[Char] 
}) mkString("")

Forse questo è utile

package password.generater;

import java.util.Random;

/**
 *
 * @author dell
 */
public class PasswordGenerater {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        int length= 11;
        System.out.println(generatePswd(length));

        // TODO code application logic here
    }
    static char[] generatePswd(int len){
        System.out.println("Your Password ");
        String charsCaps="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
        String Chars="abcdefghijklmnopqrstuvwxyz";
        String nums="0123456789";
        String symbols="[email protected]#$%^&*()_+-=.,/';:?><~*/-+";
        String passSymbols=charsCaps + Chars + nums +symbols;
        Random rnd=new Random();
        char[] password=new char[len];

        for(int i=0; i<len;i++){
            password[i]=passSymbols.charAt(rnd.nextInt(passSymbols.length()));
        }
      return password;

    }
}

Non mi piace molto nessuna di queste risposte riguardo alla soluzione "semplice": S

Vorrei andare per un semplice;), puro java, un solo liner (l'entropia è basata su una lunghezza casuale della stringa e sul set di caratteri specificato):

public String randomString(int length, String characterSet) {
    return IntStream.range(0, length).map(i -> new SecureRandom().nextInt(characterSet.length())).mapToObj(randomInt -> characterSet.substring(randomInt, randomInt + 1)).collect(Collectors.joining());
}

@Test
public void buildFiveRandomStrings() {
    for (int q = 0; q < 5; q++) {
        System.out.println(randomString(10, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"));//charachterSet can basically be anything
    }
}

o (un modo un po 'più leggibile)

public String randomString(int length, String characterSet) {
    StringBuilder sb = new StringBuilder(); //consider using StringBuffer if needed
    for (int i = 0; i < length; i++) {
        int randomInt = new SecureRandom().nextInt(characterSet.length());
        sb.append(characterSet.substring(randomInt, randomInt + 1));
    }
    return sb.toString();
}

@Test
public void buildFiveRandomStrings() {
    for (int q = 0; q < 5; q++) {
        System.out.println(randomString(10, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")); //charachterSet can basically be anything
    }
}

Ma d'altra parte si può anche andare con UUID che ha una buona entropia ( 2 ):

UUID.randomUUID().toString().replace("-", "")

Spero che sia d'aiuto.


Puoi utilizzare la classe UUID con il suo messaggio getLeastSignificantBits () per ottenere 64 bit di dati casuali, quindi convertirli in un numero radix 36 (cioè una stringa composta da 0-9, AZ):

Long.toString(Math.abs( UUID.randomUUID().getLeastSignificantBits(), 36));

Questo produce una stringa lunga fino a 13 caratteri. Usiamo Math.abs () per assicurarci che non ci sia un segno meno nascosto dentro.


Ecco il codice di una riga di AbacusUtil

String.valueOf(CharStream.random('0', 'z').filter(c -> N.isLetterOrDigit(c)).limit(12).toArray())

Casuale non significa che deve essere unico. per ottenere stringhe univoche, usando:

N.uuid() // e.g.: "e812e749-cf4c-4959-8ee1-57829a69a80f". length is 36.
N.guid() // e.g.: "0678ce04e18945559ba82ddeccaabfcd". length is 32 without '-'

Si parla di "semplice", ma nel caso in cui qualcun altro stia cercando qualcosa che soddisfi requisiti di sicurezza più stringenti, si potrebbe voler dare un'occhiata a jpwgen . jpwgen è modellato su pwgen in Unix ed è molto configurabile.


import java.util.Date;
import java.util.Random;

public class RandomGenerator {

  private static Random random = new Random((new Date()).getTime());

    public static String generateRandomString(int length) {
      char[] values = {'a','b','c','d','e','f','g','h','i','j',
               'k','l','m','n','o','p','q','r','s','t',
               'u','v','w','x','y','z','0','1','2','3',
               '4','5','6','7','8','9'};

      String out = "";

      for (int i=0;i<length;i++) {
          int idx=random.nextInt(values.length);
          out += values[idx];
      }
      return out;
    }
}

import java.util.Random;

public class passGen{
    //Verison 1.0
    private static final String dCase = "abcdefghijklmnopqrstuvwxyz";
    private static final String uCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static final String sChar = "[email protected]#$%^&*";
    private static final String intChar = "0123456789";
    private static Random r = new Random();
    private static String pass = "";

    public static void main (String[] args) {
        System.out.println ("Generating pass...");
        while (pass.length () != 16){
            int rPick = r.nextInt(4);
            if (rPick == 0){
                int spot = r.nextInt(25);
                pass += dCase.charAt(spot);
            } else if (rPick == 1) {
                int spot = r.nextInt (25);
                pass += uCase.charAt(spot);
            } else if (rPick == 2) {
                int spot = r.nextInt (7);
                pass += sChar.charAt(spot);
            } else if (rPick == 3){
                int spot = r.nextInt (9);
                pass += intChar.charAt (spot);
            }
        }
        System.out.println ("Generated Pass: " + pass);
    }
}

Quindi, ciò che fa è solo aggiungere la password nella stringa e ... sì, funziona bene, controlla ... molto semplice. l'ho scritto io


public static String getRandomString(int length) {
        char[] chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRST".toCharArray();

        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < chars.length; i++) {
            char c = chars[random.nextInt(chars.length)];
            sb.append(c);
        }
        String randomStr = sb.toString();

        return randomStr;
    }

public static String randomSeriesForThreeCharacter() {
    Random r = new Random();
    String value="";
    char random_Char ;
    for(int i=0; i<10;i++)
    { 
        random_Char = (char) (48 + r.nextInt(74));
        value=value+random_char;
    }
    return value;
}




alphanumeric