Pregunta ¿Cómo generar una cadena alfanumérica aleatoria?


He estado buscando un sencillo Algoritmo Java para generar una cadena alfanumérica pseudoaleatoria. En mi situación, se usaría como un identificador único de sesión / clave que "probablemente" sería único en una generación superior a 500K (mis necesidades realmente no requieren nada mucho más sofisticado). Idealmente, podría especificar una longitud según mis necesidades de exclusividad. Por ejemplo, una cadena generada de longitud 12 puede parecerse a algo "AEYGF7K0DM1X".


1458


origen


Respuestas:


Algoritmo

Para generar una cadena aleatoria, concatenar caracteres dibujados aleatoriamente desde el conjunto de símbolos aceptables hasta que la cadena alcance la longitud deseada.

Implementación

Aquí hay un código bastante simple y muy flexible para generar identificadores aleatorios. Lea la información que sigue para notas de aplicación importantes.

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);
    }

}

Ejemplos de uso

Cree un generador inseguro para identificadores de 8 caracteres:

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

Crear un generador seguro para identificadores de sesión:

RandomString session = new RandomString();

Crea un generador con códigos fáciles de leer para imprimir. Las cadenas son más largas que las cadenas alfanuméricas completas para compensar el uso de menos símbolos:

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

Usar como identificadores de sesión

Generar identificadores de sesión que probablemente sean únicos no es lo suficientemente bueno, o simplemente usar un contador simple. Los atacantes secuestran sesiones cuando se usan identificadores predecibles.

Hay tensión entre longitud y seguridad. Los identificadores más cortos son más fáciles de adivinar, porque hay menos posibilidades. Pero los identificadores más largos consumen más almacenamiento y ancho de banda. Un conjunto más grande de símbolos ayuda, pero puede causar problemas de codificación si los identificadores se incluyen en las URL o se vuelven a introducir a mano.

La fuente subyacente de aleatoriedad, o entropía, para los identificadores de sesión debe provenir de un generador de números aleatorios diseñado para criptografía. Sin embargo, inicializar estos generadores a veces puede ser costoso o lento desde el punto de vista computacional, por lo que se debe intentar reutilizarlos cuando sea posible.

Usar como identificadores de objetos

No todas las aplicaciones requieren seguridad. La asignación aleatoria puede ser una forma eficiente para que múltiples entidades generen identificadores en un espacio compartido sin ninguna coordinación o partición. La coordinación puede ser lenta, especialmente en un entorno agrupado o distribuido, y la división de un espacio causa problemas cuando las entidades terminan con participaciones demasiado pequeñas o demasiado grandes.

Los identificadores generados sin tomar medidas para hacerlos impredecibles deberían protegerse por otros medios si un atacante pudiera verlos y manipularlos, como ocurre en la mayoría de las aplicaciones web. Debería haber un sistema de autorización separado que proteja los objetos cuyo identificador pueda ser adivinado por un atacante sin permiso de acceso.

También se debe tener cuidado de utilizar identificadores que sean lo suficientemente largos como para hacer que las colisiones sean poco probables dado el número total anticipado de identificadores. Esto se conoce como "la paradoja del cumpleaños". La probabilidad de una colisión  pag, es aproximadamente n2/ (2qX), dónde norte es la cantidad de identificadores realmente generados, q es la cantidad de símbolos distintos en el alfabeto, y X es la longitud de los identificadores. Este debería ser un número muy pequeño, como 2-50 o menos.

Al resolver esto, se muestra que la probabilidad de colisión entre 500k identificadores de 15 caracteres es de aproximadamente 2-52, que es probablemente menos probable que los errores no detectados de los rayos cósmicos, etc.

Comparación con UUIDs

De acuerdo con su especificación, los UUID no están diseñados para ser impredecibles, y no debería ser utilizado como identificadores de sesión.

Los UUID en su formato estándar ocupan mucho espacio: 36 caracteres para solo 122 bits de entropía. (No todos los bits de un UUID "aleatorio" se seleccionan aleatoriamente). Una cadena alfanumérica elegida al azar contiene más entropía en solo 21 caracteres.

UUIDs no son flexibles; tienen una estructura y un diseño estandarizados. Esta es su virtud principal, así como su principal debilidad. Al colaborar con un tercero, la estandarización que ofrecen los UUID puede ser útil. Para uso puramente interno, pueden ser ineficientes.


1396



Java proporciona una forma de hacerlo directamente. Si no quiere los guiones, son fáciles de quitar. Solo usa 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;
    }
}

Salida:

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

732



static final String AB = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static SecureRandom rnd = new SecureRandom();

String randomString( int len ){
   StringBuilder sb = new StringBuilder( len );
   for( int i = 0; i < len; i++ ) 
      sb.append( AB.charAt( rnd.nextInt(AB.length()) ) );
   return sb.toString();
}

468



Si está contento de utilizar las clases de Apache, podría usar org.apache.commons.text.RandomStringGenerator (commons-text).

Ejemplo:

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

Desde commons-lang 3.6, RandomStringUtils es obsoleto.


453



En una línea:

Long.toHexString(Double.doubleToLongBits(Math.random()));

http://mynotes.wordpress.com/2009/07/23/java-generating-random-string/


90



Puede usar la biblioteca Apache para esto: RandomStringUtils

RandomStringUtils.randomAlphanumeric(20).toUpperCase();

87



utilizando Dólar debería ser simple como:

// "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));
    }
}

produce algo como eso:

DKL1SBH9UJWC
JH7P0IT21EA5
5DTI72EO6SFU
HQUMJTEBNF7Y
1HCR6SKYWGT7

36